Initial commit

This commit is contained in:
Martin Felis
2021-11-11 21:22:24 +01:00
commit b78045ffe7
812 changed files with 421882 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
add_subdirectory(containers)
add_subdirectory(io)
add_subdirectory(maths)
add_subdirectory(memory)
add_executable(test_endianness endianness_tests.cc)
target_link_libraries(test_endianness
ozz_base
gtest)
add_test(NAME test_endianness COMMAND test_endianness)
set_target_properties(test_endianness PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_log log_tests.cc)
target_link_libraries(test_log
ozz_base
gtest)
add_test(NAME test_log COMMAND test_log)
set_target_properties(test_log PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_platform
platform_tests.cc
span_tests.cc)
target_link_libraries(test_platform
ozz_base
gtest)
add_test(NAME test_platform COMMAND test_platform)
set_target_properties(test_platform PROPERTIES FOLDER "ozz/tests/base")
# ozz_base fuse tests
set_source_files_properties(${PROJECT_BINARY_DIR}/src_fused/ozz_base.cc PROPERTIES GENERATED 1)
add_executable(test_fuse_base
log_tests.cc
platform_tests.cc
${PROJECT_BINARY_DIR}/src_fused/ozz_base.cc)
add_dependencies(test_fuse_base BUILD_FUSE_ozz_base)
target_include_directories(test_fuse_base
PUBLIC "${PROJECT_SOURCE_DIR}/include")
target_link_libraries(test_fuse_base
gtest)
add_test(NAME test_fuse_base COMMAND test_fuse_base)
set_target_properties(test_fuse_base PROPERTIES FOLDER "ozz/tests/base")
@@ -0,0 +1,22 @@
add_executable(test_intrusive_list intrusive_list_tests.cc)
target_include_directories(test_intrusive_list
PUBLIC "${PROJECT_SOURCE_DIR}/include")
target_link_libraries(test_intrusive_list
gtest)
add_test(NAME test_intrusive_list COMMAND test_intrusive_list)
set_target_properties(test_intrusive_list PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_std_containers std_containers_tests.cc)
target_link_libraries(test_std_containers
ozz_base
gtest)
add_test(NAME test_std_containers COMMAND test_std_containers)
set_target_properties(test_std_containers PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_std_containers_archive
std_containers_archive_tests.cc)
target_link_libraries(test_std_containers_archive
ozz_base
gtest)
add_test(NAME test_std_containers_archive COMMAND test_std_containers_archive)
set_target_properties(test_std_containers_archive PROPERTIES FOLDER "ozz/tests/base")
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,145 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/containers/string_archive.h"
#include "ozz/base/containers/vector_archive.h"
#include <algorithm>
#include "gtest/gtest.h"
#include "ozz/base/io/archive.h"
TEST(string, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Writes.
ozz::io::OArchive o(&stream, endianess);
ozz::string empty_o;
o << empty_o;
ozz::string small_o("Forty-six");
o << small_o;
ozz::string big_o(
"Forty-six is a Wedderburn-Etherington number, an "
"enneagonal number and a centered triangular number. It is the sum of "
"the totient function for the first twelve integers. 46 is the largest "
"even integer that can't be expressed as a sum of two abundant numbers."
"46 is the 16th semiprime. 46 is the third semiprime with a semiprime"
"aliquot sum. The aliquot sequence of 46 is (46,26,16,15,9,4,3,1,0)."
"Since it is possible to find sequences of 46 consecutive integers "
"such that each inner member shares a factor with either the first or "
"the last member, 46 is an Erdos-Woods number.");
o << big_o;
// Rewrite for the string reuse test.
ozz::string reuse_o("Forty-six");
o << reuse_o;
// Reads.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
ozz::string empty_i;
i >> empty_i;
EXPECT_STREQ(empty_o.c_str(), empty_i.c_str());
ozz::string small_i;
i >> small_i;
EXPECT_STREQ(small_o.c_str(), small_i.c_str());
ozz::string big_i;
i >> big_i;
EXPECT_STREQ(big_o.c_str(), big_i.c_str());
ozz::string reuse_i("already used string");
i >> reuse_i;
EXPECT_STREQ(reuse_o.c_str(), reuse_i.c_str());
}
}
TEST(Vector, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Writes.
ozz::io::OArchive o(&stream, endianess);
ozz::vector<int> empty_o;
o << empty_o;
ozz::vector<int> small_o(5);
std::generate(small_o.begin(), small_o.end(), std::rand);
o << small_o;
ozz::vector<int> big_o(1263);
std::generate(big_o.begin(), big_o.end(), std::rand);
o << big_o;
// Rewrite for the Vector reuse test.
ozz::vector<int> reuse_o(46);
std::generate(reuse_o.begin(), reuse_o.end(), std::rand);
o << reuse_o;
// Reads.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
ozz::vector<int> empty_i;
i >> empty_i;
EXPECT_EQ(empty_i.size(), 0u);
ozz::vector<int> small_i;
i >> small_i;
EXPECT_EQ(small_o.size(), small_i.size());
for (size_t j = 0; j < empty_i.size(); ++j) {
EXPECT_EQ(small_o[j], small_i[j]);
}
ozz::vector<int> big_i;
i >> big_i;
EXPECT_EQ(big_o.size(), big_i.size());
for (size_t j = 0; j < big_i.size(); ++j) {
EXPECT_EQ(big_o[j], big_i[j]);
}
ozz::vector<int> reuse_i(3);
std::generate(reuse_i.begin(), reuse_i.end(), std::rand);
i >> reuse_i;
EXPECT_EQ(reuse_o.size(), reuse_i.size());
for (size_t j = 0; j < reuse_i.size(); ++j) {
EXPECT_EQ(reuse_o[j], reuse_i[j]);
}
}
}
@@ -0,0 +1,314 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "gtest/gtest.h"
#include "ozz/base/containers/deque.h"
#include "ozz/base/containers/list.h"
#include "ozz/base/containers/map.h"
#include "ozz/base/containers/queue.h"
#include "ozz/base/containers/set.h"
#include "ozz/base/containers/stack.h"
#include "ozz/base/containers/string.h"
#include "ozz/base/containers/unordered_map.h"
#include "ozz/base/containers/unordered_set.h"
#include "ozz/base/containers/vector.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/span.h"
TEST(Vector, Containers) {
typedef ozz::vector<int> Container;
Container container;
container.push_back(1);
container.insert(container.begin(), 0);
container.push_back(2);
container.push_back(std::move(3));
EXPECT_EQ(container[0], 0);
EXPECT_EQ(container[1], 1);
EXPECT_EQ(container[2], 2);
EXPECT_EQ(container[3], 3);
Container container2 = std::move(container);
}
TEST(VectorExtensions, Containers) {
typedef ozz::vector<int> Container;
Container container;
int* null = nullptr;
// Non-mutable access.
EXPECT_EQ(array_begin(container), null);
EXPECT_EQ(array_end(container), null);
EXPECT_EQ(array_end(container), array_begin(container));
EXPECT_TRUE(make_span(container).empty());
container.push_back(1);
container.push_back(2);
EXPECT_EQ(*array_begin(container), 1);
EXPECT_EQ(*(array_begin(container) + 1), 2);
EXPECT_EQ(array_begin(container) + 2, array_end(container));
EXPECT_NE(array_end(container), null);
EXPECT_EQ(*(array_end(container) - 2), 1);
EXPECT_EQ(array_end(container) - array_begin(container), 2);
EXPECT_EQ(make_span(container).begin(), array_begin(container));
EXPECT_EQ(make_span(container).end(), array_end(container));
const Container const_container(container);
EXPECT_EQ(*array_begin(const_container), 1);
EXPECT_EQ(*(array_begin(const_container) + 1), 2);
EXPECT_EQ(array_begin(const_container) + 2, array_end(const_container));
EXPECT_NE(array_end(const_container), null);
EXPECT_EQ(*(array_end(const_container) - 2), 1);
EXPECT_EQ(array_end(const_container) - array_begin(const_container), 2);
EXPECT_EQ(make_span(const_container).begin(), array_begin(const_container));
EXPECT_EQ(make_span(const_container).end(), array_end(const_container));
// Mutable access.
*array_begin(container) = 0;
EXPECT_EQ(*array_begin(container), 0);
EXPECT_EQ(*(array_begin(container) + 1), 2);
}
TEST(Deque, Containers) {
typedef ozz::deque<int> Container;
Container container;
container.push_back(1);
container.push_front(0);
container.push_back(2);
EXPECT_EQ(container[0], 0);
EXPECT_EQ(container[1], 1);
EXPECT_EQ(container[2], 2);
container.clear();
Container container2 = std::move(container);
}
TEST(List, Containers) {
typedef ozz::list<int> Container;
Container container;
container.push_back(1);
container.push_front(0);
container.push_back(2);
EXPECT_EQ(container.front(), 0);
EXPECT_EQ(container.back(), 2);
container.clear();
Container container2 = std::move(container);
}
TEST(Stack, Containers) {
typedef ozz::stack<int> Container;
Container container;
container.push(1);
container.push(2);
EXPECT_EQ(container.top(), 2);
container.pop();
EXPECT_EQ(container.top(), 1);
container.pop();
Container container2 = std::move(container);
}
TEST(Queue, Containers) {
{
typedef ozz::queue<int> Container;
Container container;
container.push(1);
container.push(2);
EXPECT_EQ(container.back(), 2);
EXPECT_EQ(container.front(), 1);
container.pop();
EXPECT_EQ(container.back(), 2);
container.pop();
Container container2 = std::move(container);
}
{
typedef ozz::priority_queue<int> Container;
Container container;
container.push(1);
container.push(2);
container.push(0);
EXPECT_EQ(container.top(), 2);
container.pop();
EXPECT_EQ(container.top(), 1);
container.pop();
EXPECT_EQ(container.top(), 0);
container.pop();
}
}
TEST(Set, Containers) {
{
typedef ozz::set<int> Container;
Container container;
EXPECT_TRUE(container.insert('c').second);
EXPECT_TRUE(container.insert('a').second);
EXPECT_TRUE(container.insert('b').second);
EXPECT_FALSE(container.insert('b').second);
EXPECT_TRUE(container.find('a') == container.begin());
EXPECT_TRUE(container.find('c') == --container.end());
EXPECT_EQ(container.erase('c'), 1u);
EXPECT_TRUE(container.find('b') == --container.end());
container.clear();
Container container2 = std::move(container);
}
{
typedef ozz::multiset<int> Container;
Container container;
container.insert('c');
container.insert('a');
container.insert('b');
container.insert('a');
EXPECT_TRUE(container.find('a') == container.begin() ||
container.find('a') == ++container.begin());
EXPECT_TRUE(container.find('c') == --container.end());
EXPECT_EQ(container.erase('c'), 1u);
EXPECT_TRUE(container.find('c') == container.end());
EXPECT_EQ(container.erase('a'), 2u);
EXPECT_TRUE(container.find('a') == container.end());
container.clear();
}
}
TEST(UnorderedSet, Containers) {
{
typedef ozz::unordered_set<int> Container;
Container container;
EXPECT_TRUE(container.insert('c').second);
EXPECT_TRUE(container.insert('a').second);
EXPECT_TRUE(container.insert('b').second);
EXPECT_FALSE(container.insert('a').second);
EXPECT_TRUE(container.find('a') != container.end());
EXPECT_TRUE(container.find('c') != container.end());
EXPECT_EQ(container.erase('c'), 1u);
EXPECT_TRUE(container.find('c') == container.end());
container.clear();
}
{
typedef ozz::unordered_multiset<int> Container;
Container container;
container.insert('c');
container.insert('a');
container.insert('b');
container.insert('a');
EXPECT_TRUE(container.find('a') != container.end());
EXPECT_TRUE(container.find('c') != container.end());
EXPECT_EQ(container.erase('c'), 1u);
EXPECT_TRUE(container.find('c') == container.end());
EXPECT_EQ(container.erase('a'), 2u);
EXPECT_TRUE(container.find('a') == container.end());
container.clear();
}
}
TEST(Map, Containers) {
{
typedef ozz::map<char, int> Container;
Container container;
container['a'] = -3;
container['c'] = -1;
container['b'] = -2;
container['d'] = 1;
EXPECT_EQ(container['a'], -3);
EXPECT_EQ(container['b'], -2);
EXPECT_EQ(container['c'], -1);
EXPECT_EQ(container['d'], 1);
EXPECT_EQ(container.erase('d'), 1u);
EXPECT_TRUE(container.find('d') == container.end());
container.clear();
Container container2 = std::move(container);
}
{
typedef ozz::multimap<char, int> Container;
Container container;
container.insert(std::pair<char, int>('a', -3));
container.insert(std::pair<char, int>('c', -1));
container.insert(std::pair<char, int>('b', -2));
container.insert(std::pair<char, int>('d', 1));
container.insert(std::pair<char, int>('d', 2));
EXPECT_EQ(container.find('a')->second, -3);
EXPECT_EQ(container.find('b')->second, -2);
EXPECT_EQ(container.find('c')->second, -1);
EXPECT_TRUE(container.find('d')->second == 1 ||
container.find('d')->second == 2);
EXPECT_EQ(container.erase('d'), 2u);
EXPECT_TRUE(container.find('d') == container.end());
container.clear();
}
}
TEST(UnorderedMap, Containers) {
{
typedef ozz::unordered_map<char, int> Container;
Container container;
container['a'] = -3;
container['c'] = -1;
container['b'] = -2;
container['d'] = 1;
EXPECT_EQ(container['a'], -3);
EXPECT_EQ(container['b'], -2);
EXPECT_EQ(container['c'], -1);
EXPECT_EQ(container['d'], 1);
EXPECT_EQ(container.erase('d'), 1u);
EXPECT_TRUE(container.find('d') == container.end());
container.clear();
}
{
typedef ozz::unordered_multimap<char, int> Container;
Container container;
container.insert(std::pair<char, int>('a', -3));
container.insert(std::pair<char, int>('c', -1));
container.insert(std::pair<char, int>('b', -2));
container.insert(std::pair<char, int>('d', 1));
container.insert(std::pair<char, int>('d', 2));
EXPECT_EQ(container.find('a')->second, -3);
EXPECT_EQ(container.find('b')->second, -2);
EXPECT_EQ(container.find('c')->second, -1);
EXPECT_TRUE(container.find('d')->second == 1 ||
container.find('d')->second == 2);
EXPECT_EQ(container.erase('d'), 2u);
EXPECT_TRUE(container.find('d') == container.end());
container.clear();
}
}
TEST(string, Containers) {
typedef ozz::string string;
string str;
EXPECT_EQ(str.size(), 0u);
str += "a string";
EXPECT_STREQ(str.c_str(), "a string");
string str2 = std::move(str);
EXPECT_STREQ(str2.c_str(), "a string");
str2.clear();
EXPECT_EQ(str2.size(), 0u);
}
+103
View File
@@ -0,0 +1,103 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/endianness.h"
#include "gtest/gtest.h"
TEST(NativeEndianness, Endianness) {
// Uses pre-defined macro to check know endianness.
// Endianness detection does not rely on this as this is not standard, but it
// helps with testing.
// x86 and x86-64 Little endian processors.
#if defined(i386) || defined(__i386__) || /*GNU C*/ \
defined(__X86__) || /*MinGW32*/ \
defined(__x86_64__) || /*Intel C/C++*/ \
defined(_M_IX86) || /*Visual Studio*/ \
defined(_M_X64) /*Visual Studio*/
EXPECT_EQ(ozz::GetNativeEndianness(), ozz::kLittleEndian);
#endif
// PowerPc Big endian processors.
#if defined(__POWERPC__) || defined(__ppc__) || \
defined(__powerpc__) || /*GNU C*/ \
defined(__IA64__) || defined(__ia64__) || \
defined(_M_PPC) /*Visual Studio*/
EXPECT_EQ(ozz::GetNativeEndianness(), ozz::kBigEndian);
#endif
// Itanium Big endian processors.
#if defined(_IA64) || /*GNU C*/ \
defined(_M_IA64) || /*Visual Studio*/ \
defined(_M_IA64) /*Intel C/C++*/
EXPECT_EQ(ozz::GetNativeEndianness(), ozz::kBigEndian);
#endif
}
TEST(Swap, Endianness) {
{ // 1 byte swapping.
uint8_t uo = 0x46;
EXPECT_EQ(ozz::EndianSwap(uo), 0x46);
}
{ // 1 byte array swapping.
uint8_t uo[] = {0x46, 0x58};
ozz::EndianSwap(uo, OZZ_ARRAY_SIZE(uo));
EXPECT_EQ(uo[0], 0x46);
EXPECT_EQ(uo[1], 0x58);
}
{ // 2 bytes swapping.
uint16_t uo = 0x4699;
EXPECT_EQ(ozz::EndianSwap(uo), 0x9946);
}
{ // 2 bytes array swapping.
uint16_t uo[] = {0x4699, 0x5814};
ozz::EndianSwap(uo, OZZ_ARRAY_SIZE(uo));
EXPECT_EQ(uo[0], 0x9946);
EXPECT_EQ(uo[1], 0x1458);
}
{ // 4 bytes swapping.
uint32_t uo = 0x46992715;
EXPECT_EQ(ozz::EndianSwap(uo), 0x15279946u);
}
{ // 2 bytes array swapping.
uint32_t uo[] = {0x46992715, 0x58142611};
ozz::EndianSwap(uo, OZZ_ARRAY_SIZE(uo));
EXPECT_EQ(uo[0], 0x15279946u);
EXPECT_EQ(uo[1], 0x11261458u);
}
{ // 8 bytes swapping.
uint64_t uo = 0x4699271511190417ull;
EXPECT_EQ(ozz::EndianSwap(uo), 0x1704191115279946ull);
}
{ // 8 bytes array swapping.
uint64_t uo[] = {0x4699271511190417ull, 0x5814264669080735ull};
ozz::EndianSwap(uo, OZZ_ARRAY_SIZE(uo));
EXPECT_EQ(uo[0], 0x1704191115279946ull);
EXPECT_EQ(uo[1], 0x3507086946261458ull);
}
}
+17
View File
@@ -0,0 +1,17 @@
add_executable(test_archive
archive_tests.cc
archive_tests_objects.cc
archive_tests_objects.h)
target_link_libraries(test_archive
ozz_base
gtest)
add_test(NAME test_archive COMMAND test_archive)
set_target_properties(test_archive PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_stream
stream_tests.cc)
target_link_libraries(test_stream
ozz_base
gtest)
add_test(NAME test_stream COMMAND test_stream)
set_target_properties(test_stream PROPERTIES FOLDER "ozz/tests/base")
+311
View File
@@ -0,0 +1,311 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/io/archive.h"
#include <stdint.h>
#include <cstring>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "archive_tests_objects.h"
TEST(Error, Archive) {
{ // Invalid nullptr stream.
EXPECT_ASSERTION(
void(ozz::io::OArchive(nullptr, ozz::GetNativeEndianness())),
"valid opened stream");
EXPECT_ASSERTION(void(ozz::io::IArchive(nullptr)), "valid opened stream");
}
{ // Invalid not opened streams.
ozz::io::File stream("root_that_does_not_exist:/file.ozz", "r");
EXPECT_ASSERTION(
void(ozz::io::OArchive(&stream, ozz::GetNativeEndianness())),
"valid opened stream");
EXPECT_ASSERTION(void(ozz::io::IArchive(&stream)), "valid opened stream");
}
}
TEST(Primitives, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write primitive types.
ozz::io::OArchive o(&stream, endianess);
const int8_t i8o = 46;
o << i8o;
const uint8_t ui8o = 46;
o << ui8o;
const int16_t i16o = 46;
o << i16o;
const uint16_t ui16o = 46;
o << ui16o;
const int32_t i32o = 46;
o << i32o;
const uint32_t ui32o = 46;
o << ui32o;
const int64_t i64o = 46;
o << i64o;
const uint64_t ui64o = 46;
o << ui64o;
const bool bo = true;
o << bo;
const float fo = 46.f;
o << fo;
// Read primitive types.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
int8_t i8i;
i >> i8i;
EXPECT_EQ(i8i, i8o);
uint8_t ui8i;
i >> ui8i;
EXPECT_EQ(ui8i, ui8o);
int16_t i16i;
i >> i16i;
EXPECT_EQ(i16i, i16o);
uint16_t ui16i;
i >> ui16i;
EXPECT_EQ(ui16i, ui16o);
int32_t i32i;
i >> i32i;
EXPECT_EQ(i32i, i32o);
uint32_t ui32i;
i >> ui32i;
EXPECT_EQ(ui32i, ui32o);
int64_t i64i;
i >> i64i;
EXPECT_EQ(i64i, i64o);
uint64_t ui64i;
i >> ui64i;
EXPECT_EQ(ui64i, ui64o);
bool bi;
i >> bi;
EXPECT_EQ(bi, bo);
float fi;
i >> fi;
EXPECT_EQ(fi, fo);
}
}
TEST(PrimitiveArrays, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write primitive types.
ozz::io::OArchive o(&stream, endianess);
const int8_t i8o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(i8o);
const uint8_t ui8o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(ui8o);
const int16_t i16o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(i16o);
const uint16_t ui16o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(ui16o);
const int32_t i32o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(i32o);
const uint32_t ui32o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(ui32o);
const int64_t i64o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(i64o);
const uint64_t ui64o[] = {46, 26, 14, 58, 99, 27};
o << ozz::io::MakeArray(ui64o);
const bool bo[] = {true, false, true};
o << ozz::io::MakeArray(bo);
const float fo[] = {46.f, 26.f, 14.f, 58.f, 99.f, 27.f};
o << ozz::io::MakeArray(fo);
const uint32_t* po_null = nullptr;
o << ozz::io::MakeArray(po_null, 0);
const ozz::span<const float> rfo(fo);
o << ozz::io::MakeArray(rfo);
// Read primitive types.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
int8_t i8i[OZZ_ARRAY_SIZE(i8o)];
i >> ozz::io::MakeArray(i8i);
EXPECT_EQ(std::memcmp(i8i, i8o, sizeof(i8o)), 0);
uint8_t ui8i[OZZ_ARRAY_SIZE(ui8o)];
i >> ozz::io::MakeArray(ui8i);
EXPECT_EQ(std::memcmp(ui8i, ui8o, sizeof(ui8o)), 0);
int16_t i16i[OZZ_ARRAY_SIZE(i16o)];
i >> ozz::io::MakeArray(i16i);
EXPECT_EQ(std::memcmp(i16i, i16o, sizeof(i16o)), 0);
uint16_t ui16i[OZZ_ARRAY_SIZE(ui16o)];
i >> ozz::io::MakeArray(ui16i);
EXPECT_EQ(std::memcmp(ui16i, ui16o, sizeof(ui16o)), 0);
int32_t i32i[OZZ_ARRAY_SIZE(i32o)];
i >> ozz::io::MakeArray(i32i);
EXPECT_EQ(std::memcmp(i32i, i32o, sizeof(i32o)), 0);
uint32_t ui32i[OZZ_ARRAY_SIZE(ui32o)];
i >> ozz::io::MakeArray(ui32i);
EXPECT_EQ(std::memcmp(ui32i, ui32o, sizeof(ui32o)), 0);
int64_t i64i[OZZ_ARRAY_SIZE(i64o)];
i >> ozz::io::MakeArray(i64i);
EXPECT_EQ(std::memcmp(i64i, i64o, sizeof(i64o)), 0);
uint64_t ui64i[OZZ_ARRAY_SIZE(ui64o)];
i >> ozz::io::MakeArray(ui64i);
EXPECT_EQ(std::memcmp(ui64i, ui64o, sizeof(ui64o)), 0);
bool bi[OZZ_ARRAY_SIZE(bo)];
i >> ozz::io::MakeArray(bi);
EXPECT_EQ(std::memcmp(bi, bo, sizeof(bo)), 0);
float fi[OZZ_ARRAY_SIZE(fo)];
i >> ozz::io::MakeArray(fi);
EXPECT_EQ(std::memcmp(fi, fo, sizeof(fo)), 0);
uint32_t* pi_null = nullptr;
i >> ozz::io::MakeArray(pi_null, 0);
float fi2[OZZ_ARRAY_SIZE(fo)];
ozz::span<float> rfi(fi2);
i >> ozz::io::MakeArray(rfi);
EXPECT_EQ(std::memcmp(rfi.data(), fo, sizeof(fo)), 0);
}
}
TEST(Class, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write classes.
ozz::io::OArchive o(&stream, endianess);
const Intrusive oi(46);
o << oi;
const Intrusive oi_mutable(46);
o << oi_mutable;
const Extrusive oe = {58};
o << oe;
const Extrusive oe_mutable = {58};
o << oe_mutable;
// Read classes.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
Intrusive ii;
i >> ii;
EXPECT_EQ(ii.i, oi.i);
Intrusive ii_mutable;
i >> ii_mutable;
EXPECT_EQ(ii_mutable.i, oi_mutable.i);
Extrusive ie;
i >> ie;
EXPECT_EQ(ie.i, oe.i);
Extrusive ie_mutable;
i >> ie_mutable;
EXPECT_EQ(ie_mutable.i, oe_mutable.i);
}
}
TEST(ClassArrays, Archive) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write classes.
ozz::io::OArchive o(&stream, endianess);
const Intrusive oi[12];
o << ozz::io::MakeArray(oi);
const Extrusive oe[] = {{46}, {58}, {14}, {26}, {99}};
o << ozz::io::MakeArray(oe);
// Read classes.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
Intrusive ii[OZZ_ARRAY_SIZE(oi)];
i >> ozz::io::MakeArray(ii);
EXPECT_EQ(std::memcmp(oi, ii, sizeof(oi)), 0);
Extrusive ie[OZZ_ARRAY_SIZE(oe)];
i >> ozz::io::MakeArray(ie);
EXPECT_EQ(std::memcmp(oe, ie, sizeof(oe)), 0);
}
}
TEST(Tag, Archive) {
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Writes to archive.
ozz::io::OArchive o(&stream, ozz::GetNativeEndianness());
Tagged1 ot;
o << ot;
// Reads from archive.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
// Tests and reads a wrong object (different tag).
OZZ_IF_DEBUG(Tagged2 it2);
EXPECT_FALSE(i.TestTag<Tagged2>());
EXPECT_ASSERTION(i >> it2, "Type tag does not match archive content.");
// Reads the right object (different tag).
Tagged1 it1;
EXPECT_TRUE(i.TestTag<Tagged1>());
EXPECT_NO_FATAL_FAILURE(i >> it1);
}
TEST(TagEOF, Archive) {
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Writes to archive n elements.
const int n_writes = 10;
ozz::io::OArchive o(&stream, ozz::GetNativeEndianness());
for (int i = 0; i < n_writes; ++i) {
Tagged1 ot;
o << ot;
}
// Reads from archive.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
EXPECT_FALSE(i.TestTag<Tagged2>());
// Tests and reads all objects.
int n_read = 0;
while (i.TestTag<Tagged1>()) {
Tagged1 it;
i >> it;
++n_read;
}
EXPECT_EQ(n_read, n_writes);
EXPECT_FALSE(i.TestTag<Tagged2>());
}
@@ -0,0 +1,60 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "archive_tests_objects.h"
#include "gtest/gtest.h"
#include "ozz/base/io/archive.h"
void Intrusive::Save(ozz::io::OArchive& _archive) const { _archive << i; }
void Intrusive::Load(ozz::io::IArchive& _archive, uint32_t _version) {
EXPECT_EQ(_version, 46u);
_archive >> i;
}
namespace ozz {
namespace io {
// Specializes Extrusive type external Save and Load functions.
void Extern<Extrusive>::Save(OArchive& _archive, const Extrusive* _test,
size_t _count) {
_archive << ozz::io::MakeArray(&_test->i, _count);
}
void Extern<Extrusive>::Load(IArchive& _archive, Extrusive* _test,
size_t _count, uint32_t _version) {
EXPECT_EQ(_version, 0u);
_archive >> ozz::io::MakeArray(&_test->i, _count);
}
} // namespace io
} // namespace ozz
void Tagged1::Save(ozz::io::OArchive& /*_archive*/) const {}
void Tagged1::Load(ozz::io::IArchive& /*_archive*/, uint32_t /*_version*/) {}
void Tagged2::Save(ozz::io::OArchive& /*_archive*/) const {}
void Tagged2::Load(ozz::io::IArchive& /*_archive*/, uint32_t /*_version*/) {}
@@ -0,0 +1,90 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_TEST_BASE_IO_ARCHIVE_TESTS_OBJECTS_H_
#define OZZ_TEST_BASE_IO_ARCHIVE_TESTS_OBJECTS_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace io {
class OArchive;
class IArchive;
} // namespace io
} // namespace ozz
struct Intrusive {
explicit Intrusive(int32_t _i = 12) : i(_i) {}
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
int32_t i;
};
struct Extrusive {
uint64_t i;
};
namespace ozz {
namespace io {
// Give Intrusive type a version.
OZZ_IO_TYPE_VERSION(46, Intrusive)
// Extrusive is not versionable.
OZZ_IO_TYPE_NOT_VERSIONABLE(Extrusive)
// Specializes Extrusive type external Save and Load functions.
template <>
struct Extern<Extrusive> {
static void Save(OArchive& _archive, const Extrusive* _test, size_t _count);
static void Load(IArchive& _archive, Extrusive* _test, size_t _count,
uint32_t _version);
};
} // namespace io
} // namespace ozz
class Tagged1 {
public:
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
};
class Tagged2 {
public:
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
};
namespace ozz {
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE(Tagged1)
OZZ_IO_TYPE_TAG("tagged1", Tagged1)
OZZ_IO_TYPE_NOT_VERSIONABLE(Tagged2)
OZZ_IO_TYPE_TAG("tagged2", Tagged2)
} // namespace io
} // namespace ozz
#endif // OZZ_TEST_BASE_IO_ARCHIVE_TESTS_OBJECTS_H_
+187
View File
@@ -0,0 +1,187 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/io/stream.h"
#include <stdint.h>
#include <limits>
#include "gtest/gtest.h"
#include "ozz/base/platform.h"
void TestStream(ozz::io::Stream* _stream) {
ASSERT_TRUE(_stream->opened());
EXPECT_EQ(_stream->Size(), 0u);
EXPECT_EQ(_stream->Seek(0, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 0);
typedef int Type;
const Type to_write = 46;
EXPECT_EQ(_stream->Write(&to_write, sizeof(Type)), sizeof(Type));
EXPECT_EQ(_stream->Tell(), static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Seek(0, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_EQ(_stream->Size(), sizeof(Type));
Type to_read = 0;
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), sizeof(Type));
EXPECT_EQ(to_read, to_write);
EXPECT_EQ(_stream->Tell(), static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Size(), sizeof(Type));
}
void TestSeek(ozz::io::Stream* _stream) {
ASSERT_TRUE(_stream->opened());
EXPECT_EQ(_stream->Seek(0, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_EQ(_stream->Size(), 0u);
// Seeking before file's begin.
EXPECT_NE(_stream->Seek(-1, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_NE(_stream->Seek(-1, ozz::io::Stream::kCurrent), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_NE(_stream->Seek(-1, ozz::io::Stream::kEnd), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_EQ(_stream->Size(), 0u);
// Bad seek argument.
EXPECT_EQ(_stream->Seek(46, ozz::io::Stream::Origin(27)), -1);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_EQ(_stream->Size(), 0u);
typedef int Type;
const Type to_write = 46;
EXPECT_EQ(_stream->Write(&to_write, sizeof(Type)), sizeof(Type));
EXPECT_EQ(_stream->Tell(), static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Size(), sizeof(Type));
const int64_t kEnd = 465827;
// Force file length to kEnd but do not write to the stream.
EXPECT_EQ(_stream->Seek(kEnd - _stream->Tell(), ozz::io::Stream::kCurrent),
0);
EXPECT_EQ(_stream->Tell(), kEnd);
EXPECT_EQ(_stream->Size(), sizeof(Type));
Type to_read = 0;
EXPECT_EQ(_stream->Seek(0, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Size(), sizeof(Type));
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), sizeof(Type));
EXPECT_EQ(to_read, to_write);
EXPECT_EQ(_stream->Tell(), static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), 0u);
EXPECT_EQ(_stream->Tell(), static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Size(), sizeof(Type));
// Force file length to kEnd + sizeof(Type) and write to the stream.
EXPECT_EQ(
_stream->Seek(kEnd - _stream->Tell() - static_cast<int>(sizeof(Type)),
ozz::io::Stream::kCurrent),
0);
EXPECT_EQ(_stream->Tell(), kEnd - static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Write(&to_write, sizeof(Type)), sizeof(Type));
EXPECT_EQ(_stream->Tell(), kEnd);
EXPECT_EQ(
_stream->Seek(-static_cast<int>(sizeof(Type)), ozz::io::Stream::kEnd), 0);
EXPECT_EQ(_stream->Tell(), kEnd - static_cast<int>(sizeof(Type)));
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), sizeof(Type));
EXPECT_EQ(to_read, to_write);
EXPECT_EQ(_stream->Tell(), kEnd);
EXPECT_EQ(
_stream->Seek(-static_cast<int>(sizeof(Type)) * 2, ozz::io::Stream::kEnd),
0);
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), sizeof(Type));
EXPECT_EQ(to_read, 0);
EXPECT_EQ(_stream->Tell(), kEnd - static_cast<int>(sizeof(Type)));
// Rewind from kEnd.
EXPECT_EQ(_stream->Seek(-kEnd, ozz::io::Stream::kEnd), 0);
EXPECT_EQ(_stream->Tell(), 0);
EXPECT_EQ(_stream->Seek(kEnd, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), kEnd);
// Read at the end of the file.
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), 0u);
EXPECT_EQ(_stream->Tell(), kEnd);
// Read after a seek beyond the end of the file.
EXPECT_EQ(_stream->Seek(4, ozz::io::Stream::kCurrent), 0);
EXPECT_EQ(_stream->Tell(), kEnd + 4);
EXPECT_EQ(_stream->Read(&to_read, sizeof(Type)), 0u);
EXPECT_EQ(_stream->Tell(), kEnd + 4);
EXPECT_EQ(_stream->Size(), static_cast<size_t>(kEnd));
}
void TestTooBigStream(ozz::io::Stream* _stream) {
const int max_size = std::numeric_limits<int>::max();
ASSERT_TRUE(_stream->opened());
EXPECT_EQ(_stream->Seek(0, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 0);
// Seeks outside of Stream valid range.
EXPECT_EQ(_stream->Seek(max_size, ozz::io::Stream::kCurrent), 0);
EXPECT_EQ(_stream->Tell(), max_size);
EXPECT_EQ(_stream->Size(), 0u);
EXPECT_NE(_stream->Seek(max_size, ozz::io::Stream::kCurrent), 0);
EXPECT_EQ(_stream->Tell(), max_size);
EXPECT_EQ(_stream->Size(), 0u);
// Writes/Reads outside of Stream valid range.
EXPECT_EQ(_stream->Seek(1, ozz::io::Stream::kSet), 0);
EXPECT_EQ(_stream->Tell(), 1);
char c;
EXPECT_EQ(_stream->Write(&c, max_size), 0u);
EXPECT_EQ(_stream->Read(&c, max_size), 0u);
EXPECT_EQ(_stream->Size(), 0u);
}
TEST(File, Stream) {
{
ozz::io::File file(nullptr);
EXPECT_FALSE(file.opened());
}
{ EXPECT_FALSE(ozz::io::File::Exist("unexisting.file")); }
{
ozz::io::File file("test.bin", "w+t");
EXPECT_TRUE(file.opened());
TestSeek(&file);
}
{ EXPECT_TRUE(ozz::io::File::Exist("test.bin")); }
}
TEST(MemoryStream, Stream) {
{
ozz::io::MemoryStream stream;
TestStream(&stream);
}
{
ozz::io::MemoryStream stream;
TestSeek(&stream);
}
{
ozz::io::MemoryStream stream;
TestTooBigStream(&stream);
}
}
+69
View File
@@ -0,0 +1,69 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/log.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
int TestFunction(std::ostream& _stream, const char* _log) {
_stream << _log << std::endl;
return 46;
}
void TestLogLevel(ozz::log::Level _level) {
ozz::log::SetLevel(_level);
EXPECT_LOG_LOGV(TestFunction(ozz::log::LogV(), "logv"), "logv");
EXPECT_LOG_LOG(TestFunction(ozz::log::Log(), "log"), "log");
EXPECT_LOG_OUT(TestFunction(ozz::log::Out(), "out"), "out");
EXPECT_LOG_ERR(TestFunction(ozz::log::Err(), "err"), "err");
EXPECT_EQ_LOG_LOGV(TestFunction(ozz::log::LogV(), "logv"), 46, "logv");
EXPECT_EQ_LOG_LOG(TestFunction(ozz::log::Log(), "log"), 46, "log");
EXPECT_EQ_LOG_OUT(TestFunction(ozz::log::Out(), "out"), 46, "out");
EXPECT_EQ_LOG_ERR(TestFunction(ozz::log::Err(), "err"), 46, "err");
}
TEST(Silent, Log) { TestLogLevel(ozz::log::kSilent); }
TEST(Standard, Log) { TestLogLevel(ozz::log::kStandard); }
TEST(Verbose, Log) { TestLogLevel(ozz::log::kVerbose); }
TEST(FloatPrecision, Log) {
const float number = 46.9352099f;
ozz::log::Log log;
ozz::log::FloatPrecision mod0(log, 0);
EXPECT_LOG_LOG(log << number << '-' << std::endl, "47-");
{
ozz::log::FloatPrecision mod2(log, 2);
EXPECT_LOG_LOG(log << number << '-' << std::endl, "46.94-");
}
EXPECT_LOG_LOG(log << number << '-' << std::endl, "47-");
}
+45
View File
@@ -0,0 +1,45 @@
add_executable(test_math
math_ex_tests.cc
box_tests.cc
rect_tests.cc
vec_float_tests.cc
quaternion_tests.cc
transform_tests.cc)
target_link_libraries(test_math
ozz_base
gtest)
add_test(NAME test_math COMMAND test_math)
set_target_properties(test_math PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_simd_math
simd_int_math_tests.cc
simd_float_math_tests.cc
simd_float4x4_tests.cc
simd_quaternion_math_tests.cc
simd_math_transpose_tests.cc)
target_link_libraries(test_simd_math
ozz_base
gtest)
add_test(NAME test_simd_math COMMAND test_simd_math)
set_target_properties(test_simd_math PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_soa_math
soa_float_tests.cc
soa_quaternion_tests.cc
soa_transform_tests.cc
soa_float4x4_tests.cc)
target_link_libraries(test_soa_math
ozz_base
gtest)
add_test(NAME test_soa_math COMMAND test_soa_math)
set_target_properties(test_soa_math PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_archive_maths
math_archive_tests.cc
simd_math_archive_tests.cc
soa_math_archive_tests.cc)
target_link_libraries(test_archive_maths
ozz_base
gtest)
add_test(NAME test_archive_maths COMMAND test_archive_maths)
set_target_properties(test_archive_maths PROPERTIES FOLDER "ozz/tests/base")
+148
View File
@@ -0,0 +1,148 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/box.h"
#include "ozz/base/maths/simd_math.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
TEST(BoxValidity, ozz_math) {
EXPECT_FALSE(ozz::math::Box().is_valid());
EXPECT_FALSE(ozz::math::Box(ozz::math::Float3(0.f, 1.f, 2.f),
ozz::math::Float3(0.f, -1.f, 2.f))
.is_valid());
EXPECT_TRUE(ozz::math::Box(ozz::math::Float3(0.f, -1.f, 2.f),
ozz::math::Float3(0.f, 1.f, 2.f))
.is_valid());
EXPECT_TRUE(ozz::math::Box(ozz::math::Float3(0.f, 1.f, 2.f),
ozz::math::Float3(0.f, 1.f, 2.f))
.is_valid());
}
TEST(BoxInside, ozz_math) {
const ozz::math::Box invalid(ozz::math::Float3(0.f, 1.f, 2.f),
ozz::math::Float3(0.f, -1.f, 2.f));
EXPECT_FALSE(invalid.is_valid());
EXPECT_FALSE(invalid.is_inside(ozz::math::Float3(0.f, 1.f, 2.f)));
EXPECT_FALSE(invalid.is_inside(ozz::math::Float3(0.f, -.5f, 2.f)));
EXPECT_FALSE(invalid.is_inside(ozz::math::Float3(-1.f, -2.f, -3.f)));
const ozz::math::Box valid(ozz::math::Float3(-1.f, -2.f, -3.f),
ozz::math::Float3(1.f, 2.f, 3.f));
EXPECT_TRUE(valid.is_valid());
EXPECT_FALSE(valid.is_inside(ozz::math::Float3(0.f, -3.f, 0.f)));
EXPECT_FALSE(valid.is_inside(ozz::math::Float3(0.f, 3.f, 0.f)));
EXPECT_TRUE(valid.is_inside(ozz::math::Float3(-1.f, -2.f, -3.f)));
EXPECT_TRUE(valid.is_inside(ozz::math::Float3(0.f, 0.f, 0.f)));
}
TEST(BoxMerge, ozz_math) {
const ozz::math::Box invalid1(ozz::math::Float3(0.f, 1.f, 2.f),
ozz::math::Float3(0.f, -1.f, 2.f));
EXPECT_FALSE(invalid1.is_valid());
const ozz::math::Box invalid2(ozz::math::Float3(0.f, -1.f, 2.f),
ozz::math::Float3(0.f, 1.f, -2.f));
EXPECT_FALSE(invalid2.is_valid());
const ozz::math::Box valid1(ozz::math::Float3(-1.f, -2.f, -3.f),
ozz::math::Float3(1.f, 2.f, 3.f));
EXPECT_TRUE(valid1.is_valid());
const ozz::math::Box valid2(ozz::math::Float3(0.f, 5.f, -8.f),
ozz::math::Float3(1.f, 6.f, 0.f));
EXPECT_TRUE(valid2.is_valid());
// Both boxes are invalid.
EXPECT_FALSE(Merge(invalid1, invalid2).is_valid());
// One box is invalid.
EXPECT_TRUE(Merge(invalid1, valid1).is_valid());
EXPECT_TRUE(Merge(valid1, invalid1).is_valid());
// Both boxes are valid.
const ozz::math::Box merge = Merge(valid1, valid2);
EXPECT_FLOAT3_EQ(merge.min, -1.f, -2.f, -8.f);
EXPECT_FLOAT3_EQ(merge.max, 1.f, 6.f, 3.f);
}
TEST(BoxTransform, ozz_math) {
const ozz::math::Box a(ozz::math::Float3(1.f, 2.f, 3.f),
ozz::math::Float3(4.f, 5.f, 6.f));
const ozz::math::Box ia = TransformBox(ozz::math::Float4x4::identity(), a);
EXPECT_FLOAT3_EQ(ia.min, 1.f, 2.f, 3.f);
EXPECT_FLOAT3_EQ(ia.max, 4.f, 5.f, 6.f);
const ozz::math::Box ta =
TransformBox(ozz::math::Float4x4::Translation(
ozz::math::simd_float4::Load(2.f, -2.f, 3.f, 0.f)),
a);
EXPECT_FLOAT3_EQ(ta.min, 3.f, 0.f, 6.f);
EXPECT_FLOAT3_EQ(ta.max, 6.f, 3.f, 9.f);
const ozz::math::Box ra =
TransformBox(ozz::math::Float4x4::FromAxisAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::LoadX(ozz::math::kPi)),
a);
EXPECT_FLOAT3_EQ(ra.min, -4.f, 2.f, -6.f);
EXPECT_FLOAT3_EQ(ra.max, -1.f, 5.f, -3.f);
}
TEST(BoxBuild, ozz_math) {
const struct {
ozz::math::Float3 value;
char pad;
} points[] = {
{ozz::math::Float3(0.f, 0.f, 0.f), 0},
{ozz::math::Float3(1.f, -1.f, 0.f), 0},
{ozz::math::Float3(0.f, 0.f, 46.f), 0},
{ozz::math::Float3(-27.f, 0.f, 0.f), 0},
{ozz::math::Float3(0.f, 58.f, 0.f), 0},
};
// Builds from a single point
const ozz::math::Box single_valid(points[1].value);
EXPECT_TRUE(single_valid.is_valid());
EXPECT_FLOAT3_EQ(single_valid.min, 1.f, -1.f, 0.f);
EXPECT_FLOAT3_EQ(single_valid.max, 1.f, -1.f, 0.f);
// Builds from multiple points
EXPECT_ASSERTION(ozz::math::Box(&points->value, 1, OZZ_ARRAY_SIZE(points)),
"_stride must be greater or equal to sizeof\\(Float3\\)");
const ozz::math::Box multi_invalid(&points->value, sizeof(points[0]), 0);
EXPECT_FALSE(multi_invalid.is_valid());
const ozz::math::Box multi_valid(&points->value, sizeof(points[0]),
OZZ_ARRAY_SIZE(points));
EXPECT_TRUE(multi_valid.is_valid());
EXPECT_FLOAT3_EQ(multi_valid.min, -27.f, -1.f, 0.f);
EXPECT_FLOAT3_EQ(multi_valid.max, 1.f, 58.f, 46.f);
}
@@ -0,0 +1,105 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/math_archive.h"
#include "gtest/gtest.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/io/archive.h"
#include "ozz/base/maths/box.h"
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/rect.h"
#include "ozz/base/maths/transform.h"
#include "ozz/base/maths/vec_float.h"
TEST(MathArchive, ozz_math) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write math types.
ozz::io::OArchive o(&stream, endianess);
const ozz::math::Float2 of2(46.f, 69.f);
o << of2;
const ozz::math::Float3 of3(46.f, 69.f, 58.f);
o << of3;
const ozz::math::Float4 of4(46.f, 69.f, 58.f, 35.f);
o << of4;
const ozz::math::Quaternion oquat(46.f, 69.f, 58.f, 35.f);
o << oquat;
const ozz::math::Transform otrans = {of3, oquat, of3};
o << otrans;
const ozz::math::Box o_box(ozz::math::Float3(14.f, 26.f, 46.f),
ozz::math::Float3(58.f, 69.f, 99.f));
o << o_box;
const ozz::math::RectFloat o_rect_float(46.f, 69.f, 58.f, 35.f);
o << o_rect_float;
const ozz::math::RectInt o_rect_int(46, 69, 58, 35);
o << o_rect_int;
// Reads math types.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
ozz::math::Float2 if2;
i >> if2;
EXPECT_FLOAT2_EQ(if2, 46.f, 69.f);
ozz::math::Float3 if3;
i >> if3;
EXPECT_FLOAT3_EQ(if3, 46.f, 69.f, 58.f);
ozz::math::Float4 if4;
i >> if4;
EXPECT_FLOAT4_EQ(if4, 46.f, 69.f, 58.f, 35.f);
ozz::math::Quaternion iquat;
i >> iquat;
EXPECT_QUATERNION_EQ(iquat, 46.f, 69.f, 58.f, 35.f);
ozz::math::Transform itrans;
i >> itrans;
EXPECT_FLOAT3_EQ(itrans.translation, 46.f, 69.f, 58.f);
EXPECT_QUATERNION_EQ(itrans.rotation, 46.f, 69.f, 58.f, 35.f);
EXPECT_FLOAT3_EQ(itrans.scale, 46.f, 69.f, 58.f);
ozz::math::Box i_box;
i >> i_box;
EXPECT_FLOAT3_EQ(i_box.min, 14.f, 26.f, 46.f);
EXPECT_FLOAT3_EQ(i_box.max, 58.f, 69.f, 99.f);
ozz::math::RectFloat i_rect_float;
i >> i_rect_float;
EXPECT_FLOAT_EQ(i_rect_float.left, 46.f);
EXPECT_FLOAT_EQ(i_rect_float.bottom, 69.f);
EXPECT_FLOAT_EQ(i_rect_float.width, 58.f);
EXPECT_FLOAT_EQ(i_rect_float.height, 35.f);
ozz::math::RectInt i_rect_int;
i >> i_rect_int;
EXPECT_EQ(i_rect_int.left, 46);
EXPECT_EQ(i_rect_int.bottom, 69);
EXPECT_EQ(i_rect_int.width, 58);
EXPECT_EQ(i_rect_int.height, 35);
}
}
+98
View File
@@ -0,0 +1,98 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
TEST(Trigonometry, ozz_math_ex) {
EXPECT_FLOAT_EQ(ozz::math::kPi, 3.1415926535897932384626433832795f);
EXPECT_FLOAT_EQ(ozz::math::kPi * ozz::math::kRadianToDegree, 180.f);
EXPECT_FLOAT_EQ(180.f * ozz::math::kDegreeToRadian, ozz::math::kPi);
}
TEST(FloatArithmetic, ozz_math_ex) {
EXPECT_FLOAT_EQ(ozz::math::Lerp(0.f, 1.f, 0.f), 0.f);
EXPECT_FLOAT_EQ(ozz::math::Lerp(0.f, 1.f, 1.f), 1.f);
EXPECT_FLOAT_EQ(ozz::math::Lerp(0.f, 1.f, .3f), .3f);
EXPECT_FLOAT_EQ(ozz::math::Lerp(0.f, 1.f, 12.f), 12.f);
EXPECT_FLOAT_EQ(ozz::math::Lerp(0.f, 1.f, -12.f), -12.f);
}
TEST(FloatComparison, ozz_math_ex) {
const float a = {.5f};
const float b = {4.f};
const float c = {2.f};
const float min = ozz::math::Min(a, b);
EXPECT_FLOAT_EQ(min, a);
const float max = ozz::math::Max(a, b);
EXPECT_FLOAT_EQ(max, b);
const float clamp = ozz::math::Clamp(a, c, b);
EXPECT_FLOAT_EQ(clamp, c);
const float clamp0 = ozz::math::Clamp(a, b, c);
EXPECT_FLOAT_EQ(clamp0, c);
const float clamp1 = ozz::math::Clamp(c, a, b);
EXPECT_FLOAT_EQ(clamp1, c);
}
TEST(Select, ozz_math_ex) {
int a = -27, b = 46;
int *pa = &a, *pb = &b;
int *cpa = &a, *cpb = &b;
{ // Integer select
EXPECT_EQ(ozz::math::Select(true, a, b), a);
EXPECT_EQ(ozz::math::Select(true, b, a), b);
EXPECT_EQ(ozz::math::Select(false, a, b), b);
}
{ // Float select
EXPECT_FLOAT_EQ(ozz::math::Select(true, 46.f, 27.f), 46.f);
EXPECT_FLOAT_EQ(ozz::math::Select(false, 99.f, 46.f), 46.f);
}
{ // Pointer select
EXPECT_EQ(ozz::math::Select(true, pa, pb), pa);
EXPECT_EQ(ozz::math::Select(true, pb, pa), pb);
EXPECT_EQ(ozz::math::Select(false, pa, pb), pb);
}
{ // Const pointer select
EXPECT_EQ(ozz::math::Select(true, cpa, cpb), cpa);
EXPECT_EQ(ozz::math::Select(true, cpb, cpa), cpb);
EXPECT_EQ(ozz::math::Select(false, cpa, cpb), cpb);
EXPECT_EQ(ozz::math::Select(false, pa, cpb), cpb);
}
}
@@ -0,0 +1,469 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/quaternion.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::Float3;
using ozz::math::Float4;
using ozz::math::Quaternion;
TEST(QuaternionConstant, ozz_math) {
EXPECT_QUATERNION_EQ(Quaternion::identity(), 0.f, 0.f, 0.f, 1.f);
}
TEST(QuaternionAxisAngle, ozz_math) {
// Expect assertions from invalid inputs
EXPECT_ASSERTION(Quaternion::FromAxisAngle(Float3::zero(), 0.f),
"axis is not normalized");
EXPECT_ASSERTION(ToAxisAngle(Quaternion(0.f, 0.f, 0.f, 2.f)), "IsNormalized");
// Identity
EXPECT_QUATERNION_EQ(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f), 0.f,
0.f, 0.f, 1.f);
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion::identity()), 1.f, 0.f, 0.f, 0.f);
// Other axis angles
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisAngle(Float3::y_axis(), ozz::math::kPi_2), 0.f,
.70710677f, 0.f, .70710677f);
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion(0.f, .70710677f, 0.f, .70710677f)),
0.f, 1.f, 0.f, ozz::math::kPi_2);
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisAngle(Float3::y_axis(), -ozz::math::kPi_2), 0.f,
-.70710677f, 0.f, .70710677f);
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisAngle(-Float3::y_axis(), ozz::math::kPi_2), 0.f,
-.70710677f, 0.f, .70710677f);
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion(0.f, -.70710677f, 0.f, .70710677f)),
0.f, -1.f, 0.f, ozz::math::kPi_2);
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisAngle(Float3::y_axis(), 3.f * ozz::math::kPi_4), 0.f,
0.923879504f, 0.f, 0.382683426f);
EXPECT_FLOAT4_EQ(
ToAxisAngle(Quaternion(0.f, 0.923879504f, 0.f, 0.382683426f)), 0.f, 1.f,
0.f, 3.f * ozz::math::kPi_4);
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisAngle(Float3(.819865f, .033034f, -.571604f), 1.123f),
.4365425f, .017589169f, -.30435428f, .84645736f);
EXPECT_FLOAT4_EQ(
ToAxisAngle(Quaternion(.4365425f, .017589169f, -.30435428f, .84645736f)),
.819865f, .033034f, -.571604f, 1.123f);
}
TEST(QuaternionAxisCosAngle, ozz_math) {
// Expect assertions from invalid inputs
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::zero(), 0.f),
"axis is not normalized");
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::y_axis(), -1.0000001f),
"cos is not in \\[-1,1\\] range.");
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::y_axis(), 1.0000001f),
"cos is not in \\[-1,1\\] range.");
// Identity
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(Float3::y_axis(), 1.f), 0.f,
0.f, 0.f, 1.f);
// Other axis angles
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(Float3::y_axis(),
std::cos(ozz::math::kPi_2)),
0.f, .70710677f, 0.f, .70710677f);
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(-Float3::y_axis(),
std::cos(ozz::math::kPi_2)),
0.f, -.70710677f, 0.f, .70710677f);
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(
Float3::y_axis(), std::cos(3.f * ozz::math::kPi_4)),
0.f, 0.923879504f, 0.f, 0.382683426f);
EXPECT_QUATERNION_EQ(
Quaternion::FromAxisCosAngle(Float3(.819865f, .033034f, -.571604f),
std::cos(1.123f)),
.4365425f, .017589169f, -.30435428f, .84645736f);
}
TEST(QuaternionQuaternionEuler, ozz_math) {
// Identity
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, 0.f, 0.f), 0.f, 0.f, 0.f,
1.f);
EXPECT_FLOAT3_EQ(ToEuler(Quaternion::identity()), 0.f, 0.f, 0.f);
// Heading
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(ozz::math::kPi_2, 0.f, 0.f), 0.f,
.70710677f, 0.f, .70710677f);
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(0.f, .70710677f, 0.f, .70710677f)),
ozz::math::kPi_2, 0.f, 0.f);
// Elevation
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, ozz::math::kPi_2, 0.f), 0.f,
0.f, .70710677f, .70710677f);
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(0.f, 0.f, .70710677f, .70710677f)), 0.f,
ozz::math::kPi_2, 0.f);
// Bank
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi_2),
.70710677f, 0.f, 0.f, .70710677f);
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(.70710677f, 0.f, 0.f, .70710677f)), 0.f,
0.f, ozz::math::kPi_2);
// Any rotation
EXPECT_QUATERNION_EQ(
Quaternion::FromEuler(ozz::math::kPi / 4.f, -ozz::math::kPi / 6.f,
ozz::math::kPi_2),
.56098551f, .092295974f, -0.43045932f, .70105737f);
EXPECT_FLOAT3_EQ(
ToEuler(Quaternion(.56098551f, .092295974f, -0.43045932f, .70105737f)),
ozz::math::kPi / 4.f, -ozz::math::kPi / 6.f, ozz::math::kPi_2);
}
TEST(QuaternionFromVectors, ozz_math) {
// Returns identity for a 0 length vector
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::zero(), Float3::x_axis()), 0.f, 0.f, 0.f,
1.f);
// pi/2 around y
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::z_axis(), Float3::x_axis()), 0.f,
0.707106769f, 0.f, 0.707106769f);
// Non unit pi/2 around y
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::z_axis() * 7.f, Float3::x_axis()), 0.f,
0.707106769f, 0.f, 0.707106769f);
// Minus pi/2 around y
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::x_axis(), Float3::z_axis()), 0.f,
-0.707106769f, 0.f, 0.707106769f);
// pi/2 around x
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::y_axis(), Float3::z_axis()), 0.707106769f,
0.f, 0.f, 0.707106769f);
// Non unit pi/2 around x
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::y_axis() * 9.f, Float3::z_axis() * 13.f),
0.707106769f, 0.f, 0.f, 0.707106769f);
// pi/2 around z
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::x_axis(), Float3::y_axis()), 0.f, 0.f,
0.707106769f, 0.707106769f);
// pi/2 around z also
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3(0.707106769f, 0.707106769f, 0.f),
Float3(-0.707106769f, 0.707106769f, 0.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Aligned vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::x_axis(), Float3::x_axis()), 0.f, 0.f,
0.f, 1.f);
// Non-unit aligned vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::x_axis(), Float3::x_axis() * 2.f), 0.f,
0.f, 0.f, 1.f);
// Opposed vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::x_axis(), -Float3::x_axis()), 0.f, 1.f,
0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(-Float3::x_axis(), Float3::x_axis()), 0.f, -1.f,
0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::y_axis(), -Float3::y_axis()), 0.f, 0.f,
1.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(-Float3::y_axis(), Float3::y_axis()), 0.f, 0.f,
-1.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3::z_axis(), -Float3::z_axis()), 0.f, -1.f,
0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(-Float3::z_axis(), Float3::z_axis()), 0.f, 1.f,
0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3(0.707106769f, 0.707106769f, 0.f),
-Float3(0.707106769f, 0.707106769f, 0.f)),
-0.707106769f, 0.707106769f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3(0.f, 0.707106769f, 0.707106769f),
-Float3(0.f, 0.707106769f, 0.707106769f)),
0.f, -0.707106769f, 0.707106769f, 0);
// Non-unit opposed vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromVectors(Float3(2.f, 2.f, 2.f), -Float3(2.f, 2.f, 2.f)),
0.f, -0.707106769f, 0.707106769f, 0);
}
TEST(QuaternionFromUnitVectors, ozz_math) {
// assert 0 length vectors
EXPECT_ASSERTION(
Quaternion::FromUnitVectors(Float3::zero(), Float3::x_axis()),
"Input vectors must be normalized.");
EXPECT_ASSERTION(
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::zero()),
"Input vectors must be normalized.");
// assert non unit vectors
EXPECT_ASSERTION(
Quaternion::FromUnitVectors(Float3::x_axis() * 2.f, Float3::x_axis()),
"Input vectors must be normalized.");
EXPECT_ASSERTION(
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::x_axis() * .5f),
"Input vectors must be normalized.");
// pi/2 around y
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::z_axis(), Float3::x_axis()), 0.f,
0.707106769f, 0.f, 0.707106769f);
// Minus pi/2 around y
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::z_axis()), 0.f,
-0.707106769f, 0.f, 0.707106769f);
// pi/2 around x
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::y_axis(), Float3::z_axis()),
0.707106769f, 0.f, 0.f, 0.707106769f);
// pi/2 around z
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::y_axis()), 0.f, 0.f,
0.707106769f, 0.707106769f);
// pi/2 around z also
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3(0.707106769f, 0.707106769f, 0.f),
Float3(-0.707106769f, 0.707106769f, 0.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Aligned vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::x_axis()), 0.f, 0.f,
0.f, 1.f);
// Opposed vectors
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::x_axis(), -Float3::x_axis()), 0.f,
1.f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(-Float3::x_axis(), Float3::x_axis()), 0.f,
-1.f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::y_axis(), -Float3::y_axis()), 0.f,
0.f, 1.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(-Float3::y_axis(), Float3::y_axis()), 0.f,
0.f, -1.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3::z_axis(), -Float3::z_axis()), 0.f,
-1.f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(-Float3::z_axis(), Float3::z_axis()), 0.f,
1.f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3(0.707106769f, 0.707106769f, 0.f),
-Float3(0.707106769f, 0.707106769f, 0.f)),
-0.707106769f, 0.707106769f, 0.f, 0);
EXPECT_QUATERNION_EQ(
Quaternion::FromUnitVectors(Float3(0.f, 0.707106769f, 0.707106769f),
-Float3(0.f, 0.707106769f, 0.707106769f)),
0.f, -0.707106769f, 0.707106769f, 0);
}
TEST(QuaternionCompare, ozz_math) {
EXPECT_TRUE(Quaternion::identity() == Quaternion(0.f, 0.f, 0.f, 1.f));
EXPECT_TRUE(Quaternion::identity() != Quaternion(1.f, 0.f, 0.f, 0.f));
EXPECT_TRUE(Compare(Quaternion::identity(), Quaternion::identity(), std::cos(.5f * 0.f)));
EXPECT_TRUE(Compare(Quaternion::identity(),
Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
std::cos(.5f * ozz::math::kPi / 50.f)));
EXPECT_TRUE(Compare(Quaternion::identity(),
-Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
std::cos(.5f * ozz::math::kPi / 50.f)));
EXPECT_FALSE(Compare(Quaternion::identity(),
Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
std::cos(.5f * ozz::math::kPi / 200.f)));
}
TEST(QuaternionArithmetic, ozz_math) {
const Quaternion a(.70710677f, 0.f, 0.f, .70710677f);
const Quaternion b(0.f, .70710677f, 0.f, .70710677f);
const Quaternion c(0.f, .70710677f, 0.f, -.70710677f);
const Quaternion denorm(1.414212f, 0.f, 0.f, 1.414212f);
EXPECT_TRUE(IsNormalized(a));
EXPECT_TRUE(IsNormalized(b));
EXPECT_TRUE(IsNormalized(c));
EXPECT_FALSE(IsNormalized(denorm));
const Quaternion conjugate = Conjugate(a);
EXPECT_QUATERNION_EQ(conjugate, -a.x, -a.y, -a.z, a.w);
EXPECT_TRUE(IsNormalized(conjugate));
const Quaternion negate = -a;
EXPECT_QUATERNION_EQ(negate, -a.x, -a.y, -a.z, -a.w);
EXPECT_TRUE(IsNormalized(negate));
const Quaternion add = a + b;
EXPECT_QUATERNION_EQ(add, .70710677f, .70710677f, 0.f, 1.41421354f);
const Quaternion mul0 = a * conjugate;
EXPECT_QUATERNION_EQ(mul0, 0.f, 0.f, 0.f, 1.f);
EXPECT_TRUE(IsNormalized(mul0));
const Quaternion muls = a * 2.f;
EXPECT_QUATERNION_EQ(muls, 1.41421354f, 0.f, 0.f, 1.41421354f);
const Quaternion mul1 = conjugate * a;
EXPECT_QUATERNION_EQ(mul1, 0.f, 0.f, 0.f, 1.f);
EXPECT_TRUE(IsNormalized(mul1));
const Quaternion q1234(1.f, 2.f, 3.f, 4.f);
const Quaternion q5678(5.f, 6.f, 7.f, 8.f);
const Quaternion mul12345678 = q1234 * q5678;
EXPECT_QUATERNION_EQ(mul12345678, 24.f, 48.f, 48.f, -6.f);
EXPECT_ASSERTION(Normalize(Quaternion(0.f, 0.f, 0.f, 0.f)),
"is not normalizable");
const Quaternion normalize = Normalize(denorm);
EXPECT_TRUE(IsNormalized(normalize));
EXPECT_QUATERNION_EQ(normalize, .7071068f, 0.f, 0.f, .7071068f);
EXPECT_ASSERTION(NormalizeSafe(denorm, Quaternion(0.f, 0.f, 0.f, 0.f)),
"_safer is not normalized");
const Quaternion normalize_safe =
NormalizeSafe(denorm, Quaternion::identity());
EXPECT_TRUE(IsNormalized(normalize_safe));
EXPECT_QUATERNION_EQ(normalize_safe, .7071068f, 0.f, 0.f, .7071068f);
const Quaternion normalize_safer =
NormalizeSafe(Quaternion(0.f, 0.f, 0.f, 0.f), Quaternion::identity());
EXPECT_TRUE(IsNormalized(normalize_safer));
EXPECT_QUATERNION_EQ(normalize_safer, 0.f, 0.f, 0.f, 1.f);
const Quaternion lerp_0 = Lerp(a, b, 0.f);
EXPECT_QUATERNION_EQ(lerp_0, a.x, a.y, a.z, a.w);
const Quaternion lerp_1 = Lerp(a, b, 1.f);
EXPECT_QUATERNION_EQ(lerp_1, b.x, b.y, b.z, b.w);
const Quaternion lerp_0_2 = Lerp(a, b, .2f);
EXPECT_QUATERNION_EQ(lerp_0_2, .5656853f, .1414213f, 0.f, .7071068f);
const Quaternion nlerp_0 = NLerp(a, b, 0.f);
EXPECT_TRUE(IsNormalized(nlerp_0));
EXPECT_QUATERNION_EQ(nlerp_0, a.x, a.y, a.z, a.w);
const Quaternion nlerp_1 = NLerp(a, b, 1.f);
EXPECT_TRUE(IsNormalized(nlerp_1));
EXPECT_QUATERNION_EQ(nlerp_1, b.x, b.y, b.z, b.w);
const Quaternion nlerp_0_2 = NLerp(a, b, .2f);
EXPECT_TRUE(IsNormalized(nlerp_0_2));
EXPECT_QUATERNION_EQ(nlerp_0_2, .6172133f, .1543033f, 0.f, .7715167f);
EXPECT_ASSERTION(SLerp(denorm, b, 0.f), "IsNormalized\\(_a\\)");
EXPECT_ASSERTION(SLerp(a, denorm, 0.f), "IsNormalized\\(_b\\)");
const Quaternion slerp_0 = SLerp(a, b, 0.f);
EXPECT_TRUE(IsNormalized(slerp_0));
EXPECT_QUATERNION_EQ(slerp_0, a.x, a.y, a.z, a.w);
const Quaternion slerp_c_0 = SLerp(a, c, 0.f);
EXPECT_TRUE(IsNormalized(slerp_c_0));
EXPECT_QUATERNION_EQ(slerp_c_0, a.x, a.y, a.z, a.w);
const Quaternion slerp_c_1 = SLerp(a, c, 1.f);
EXPECT_TRUE(IsNormalized(slerp_c_1));
EXPECT_QUATERNION_EQ(slerp_c_1, c.x, c.y, c.z, c.w);
const Quaternion slerp_c_0_6 = SLerp(a, c, .6f);
EXPECT_TRUE(IsNormalized(slerp_c_0_6));
EXPECT_QUATERNION_EQ(slerp_c_0_6, .6067752f, .7765344f, 0.f, -.1697592f);
const Quaternion slerp_1 = SLerp(a, b, 1.f);
EXPECT_TRUE(IsNormalized(slerp_1));
EXPECT_QUATERNION_EQ(slerp_1, b.x, b.y, b.z, b.w);
const Quaternion slerp_0_2 = SLerp(a, b, .2f);
EXPECT_TRUE(IsNormalized(slerp_0_2));
EXPECT_QUATERNION_EQ(slerp_0_2, .6067752f, .1697592f, 0.f, .7765344f);
const Quaternion slerp_0_7 = SLerp(a, b, .7f);
EXPECT_TRUE(IsNormalized(slerp_0_7));
EXPECT_QUATERNION_EQ(slerp_0_7, .2523113f, .5463429f, 0.f, .798654f);
const float dot = Dot(a, b);
EXPECT_FLOAT_EQ(dot, .5f);
}
TEST(QuaternionTransformVector, ozz_math) {
// 0 length
EXPECT_FLOAT3_EQ(
TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f),
Float3::zero()),
0, 0, 0);
// Unit length
EXPECT_FLOAT3_EQ(
TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f),
Float3::z_axis()),
0, 0, 1);
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
ozz::math::kPi_2),
Float3::y_axis()),
0, 1, 0);
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
ozz::math::kPi_2),
Float3::x_axis()),
0, 0, -1);
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
ozz::math::kPi_2),
Float3::z_axis()),
1, 0, 0);
// Non unit
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::z_axis(),
ozz::math::kPi_2),
Float3::x_axis() * 2),
0, 2, 0);
}
+62
View File
@@ -0,0 +1,62 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/rect.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
TEST(RectInt, ozz_math) {
ozz::math::RectInt rect(10, 20, 30, 40);
EXPECT_EQ(rect.right(), 40);
EXPECT_EQ(rect.top(), 60);
EXPECT_TRUE(rect.is_inside(10, 20));
EXPECT_TRUE(rect.is_inside(39, 59));
EXPECT_FALSE(rect.is_inside(9, 20));
EXPECT_FALSE(rect.is_inside(10, 19));
EXPECT_FALSE(rect.is_inside(40, 59));
EXPECT_FALSE(rect.is_inside(39, 60));
}
TEST(RectFloat, ozz_math) {
ozz::math::RectFloat rect(10.f, 20.f, 30.f, 40.f);
EXPECT_FLOAT_EQ(rect.right(), 40.f);
EXPECT_FLOAT_EQ(rect.top(), 60.f);
EXPECT_TRUE(rect.is_inside(10.f, 20.f));
EXPECT_TRUE(rect.is_inside(39.f, 59.f));
EXPECT_FALSE(rect.is_inside(9.f, 20.f));
EXPECT_FALSE(rect.is_inside(10.f, 19.f));
EXPECT_FALSE(rect.is_inside(40.f, 59.f));
EXPECT_FALSE(rect.is_inside(39.f, 60.f));
}
@@ -0,0 +1,488 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_math.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
using ozz::math::Float4x4;
using ozz::math::SimdFloat4;
TEST(Float4x4Constant, ) {
const Float4x4 identity = Float4x4::identity();
EXPECT_FLOAT4x4_EQ(identity, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f,
1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
}
TEST(Float4x4Arithmetic, ozz_simd_math) {
const Float4x4 m0 = {{ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)}};
const Float4x4 m1 = {
{ozz::math::simd_float4::Load(-0.f, -1.f, -2.f, -3.f),
ozz::math::simd_float4::Load(-4.f, -5.f, -6.f, -7.f),
ozz::math::simd_float4::Load(-8.f, -9.f, -10.f, -11.f),
ozz::math::simd_float4::Load(-12.f, -13.f, -14.f, -15.f)}};
const Float4x4 m2 = {
{ozz::math::simd_float4::Load(0.f, -1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(-4.f, 5.f, 6.f, -7.f),
ozz::math::simd_float4::Load(8.f, -9.f, -10.f, 11.f),
ozz::math::simd_float4::Load(-12.f, 13.f, -14.f, 15.f)}};
const SimdFloat4 v = ozz::math::simd_float4::Load(-0.f, -1.f, -2.f, -3.f);
const SimdFloat4 mul_vector = m0 * v;
EXPECT_SIMDFLOAT_EQ(mul_vector, -56.f, -62.f, -68.f, -74.f);
const SimdFloat4 transform_point = TransformPoint(m0, v);
EXPECT_SIMDFLOAT_EQ(transform_point, -8.f, -10.f, -12.f, -14.f);
const SimdFloat4 transform_vector = TransformVector(m0, v);
EXPECT_SIMDFLOAT_EQ(transform_vector, -20.f, -23.f, -26.f, -29.f);
const Float4x4 mul_mat = m0 * m1;
EXPECT_FLOAT4x4_EQ(mul_mat, -56.f, -62.f, -68.f, -74.f, -152.f, -174.f,
-196.f, -218.f, -248.f, -286.f, -324.f, -362.f, -344.f,
-398.f, -452.f, -506.f);
const Float4x4 add_mat = m0 + m1;
EXPECT_FLOAT4x4_EQ(add_mat, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
const Float4x4 sub_mat = m0 - m1;
EXPECT_FLOAT4x4_EQ(sub_mat, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f, 16.f,
18.f, 20.f, 22.f, 24.f, 26.f, 28.f, 30.f);
const Float4x4 transpose = Transpose(m0);
EXPECT_FLOAT4x4_EQ(transpose, 0.f, 4.f, 8.f, 12.f, 1.f, 5.f, 9.f, 13.f, 2.f,
6.f, 10.f, 14.f, 3.f, 7.f, 11.f, 15.f);
// Invertible
const Float4x4 invert_ident = Invert(Float4x4::identity());
EXPECT_FLOAT4x4_EQ(invert_ident, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
const Float4x4 invert = Invert(m2);
EXPECT_FLOAT4x4_EQ(invert, .216667f, 2.75f, 1.6f, .066666f, .2f, 2.5f, 1.4f,
.1f, .25f, .5f, .25f, 0.f, .233333f, .5f, .3f, .03333f);
const Float4x4 invert_mul = m2 * invert;
EXPECT_FLOAT4x4_EQ(invert_mul, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
ozz::math::SimdInt4 invertible;
EXPECT_FLOAT4x4_EQ(Invert(m2, &invertible), 0.216667f, 2.75f, 1.6f, .066666f,
.2f, 2.5f, 1.4f, .1f, .25f, .5f, .25f, 0.f, .233333f, .5f,
.3f, .03333f);
EXPECT_TRUE(ozz::math::AreAllTrue1(invertible));
// Non invertible
EXPECT_ASSERTION(Invert(m0), "Matrix is not invertible");
ozz::math::SimdInt4 not_invertible;
EXPECT_FLOAT4x4_EQ(Invert(m0, &not_invertible), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_FALSE(ozz::math::AreAllTrue1(not_invertible));
}
TEST(Float4x4Normal, ozz_simd_math) {
const Float4x4 not_orthogonal = {
{ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(not_orthogonal)));
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, -1.f, 1.f, 0.f)))));
EXPECT_FALSE(ozz::math::AreAllTrue3(IsNormalized(
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, 46.f, 1.f, 0.f)))));
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(Float4x4::identity())));
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(
Float4x4::FromAxisAngle(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::LoadX(1.24f)))));
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, 0.f, 0.f, 1.f)))));
}
TEST(Float4x4Orthogonal, ozz_simd_math) {
const Float4x4 zero = {{ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
const Float4x4 not_orthogonal = {
{ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(not_orthogonal)));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(zero)));
const Float4x4 reflexion1x =
Float4x4::Scaling(ozz::math::simd_float4::Load(-1.f, 1.f, 1.f, 0.f));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion1x)));
const Float4x4 reflexion1y =
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, -1.f, 1.f, 0.f));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion1y)));
const Float4x4 reflexion1z =
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, 1.f, -1.f, 0.f));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion1z)));
const Float4x4 reflexion2x =
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, -1.f, -1.f, 0.f));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion2x)));
const Float4x4 reflexion2y =
Float4x4::Scaling(ozz::math::simd_float4::Load(-1.f, 1.f, -1.f, 0.f));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion2y)));
const Float4x4 reflexion2z =
Float4x4::Scaling(ozz::math::simd_float4::Load(-1.f, -1.f, 1.f, 0.f));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion2z)));
const Float4x4 reflexion3 =
Float4x4::Scaling(ozz::math::simd_float4::Load(-1.f, -1.f, -1.f, 0.f));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(reflexion3)));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(Float4x4::identity())));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, 0.f, 0.f, 1.f)))));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(
Float4x4::FromAxisAngle(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::LoadX(1.24f)))));
}
TEST(Float4x4Translate, ozz_simd_math) {
const SimdFloat4 v = ozz::math::simd_float4::Load(-1.f, 1.f, 2.f, 3.f);
const Float4x4 m0 = {{ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)}};
const Float4x4 translation = Float4x4::Translation(v);
EXPECT_FLOAT4x4_EQ(translation, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, -1.f, 1.f, 2.f, 1.f);
const Float4x4 translate_mul = m0 * translation;
EXPECT_FLOAT4x4_EQ(translate_mul, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f,
9.f, 10.f, 11.f, 32.f, 35.f, 38.f, 41.f);
const Float4x4 translate = Translate(m0, v);
EXPECT_FLOAT4x4_EQ(translate, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f,
9.f, 10.f, 11.f, 32.f, 35.f, 38.f, 41.f);
}
TEST(Float4x4Scale, ozz_simd_math) {
const SimdFloat4 v = ozz::math::simd_float4::Load(-1.f, 1.f, 2.f, 3.f);
const Float4x4 m0 = {{ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)}};
const Float4x4 scaling = Float4x4::Scaling(v);
EXPECT_FLOAT4x4_EQ(scaling, -1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f,
2.f, 0.f, 0.f, 0.f, 0.f, 1.f);
const Float4x4 scale_mul = m0 * scaling;
EXPECT_FLOAT4x4_EQ(scale_mul, 0.f, -1.f, -2.f, -3.f, 4.f, 5.f, 6.f, 7.f, 16.f,
18.f, 20.f, 22.f, 12.f, 13.f, 14.f, 15.f);
const Float4x4 scale = Scale(m0, v);
EXPECT_FLOAT4x4_EQ(scale, 0.f, -1.f, -2.f, -3.f, 4.f, 5.f, 6.f, 7.f, 16.f,
18.f, 20.f, 22.f, 12.f, 13.f, 14.f, 15.f);
}
TEST(Float4x4ColumnMultiply, ozz_simd_math) {
const SimdFloat4 v = ozz::math::simd_float4::Load(-1.f, -2.f, -3.f, -4.f);
const Float4x4 m0 = {{ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)}};
const Float4x4 column_multiply = ozz::math::ColumnMultiply(m0, v);
EXPECT_FLOAT4x4_EQ(column_multiply, 0.f, -2.f, -6.f, -12.f, -4.f, -10.f,
-18.f, -28.f, -8.f, -18.f, -30.f, -44.f, -12.f, -26.f,
-42.f, -60.f);
}
TEST(Float4x4Rotate, ozz_simd_math) {
const Float4x4 euler_identity =
Float4x4::FromEuler(ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f));
EXPECT_FLOAT4x4_EQ(euler_identity, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
const Float4x4 euler = Float4x4::FromEuler(
ozz::math::simd_float4::Load(ozz::math::kPi_2, 0.f, 0.f, 0.f));
EXPECT_FLOAT4x4_EQ(euler, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(euler)));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(euler)));
EXPECT_ASSERTION(Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 1.f)),
"IsNormalized");
const Float4x4 quaternion_identity = Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f));
EXPECT_FLOAT4x4_EQ(quaternion_identity, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(quaternion_identity)));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(quaternion_identity)));
const Float4x4 quaternion = Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, .70710677f));
EXPECT_FLOAT4x4_EQ(quaternion, 0.f, 0.f, -1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
EXPECT_ASSERTION(
Float4x4::FromAxisAngle(ozz::math::simd_float4::Load(1.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::zero()),
"IsNormalized");
const Float4x4 axis_angle_identity = Float4x4::FromAxisAngle(
ozz::math::simd_float4::y_axis(), ozz::math::simd_float4::zero());
EXPECT_FLOAT4x4_EQ(axis_angle_identity, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
const Float4x4 axis_angle =
Float4x4::FromAxisAngle(ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::LoadX(ozz::math::kPi_2));
EXPECT_FLOAT4x4_EQ(axis_angle, 0.f, 0.f, -1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
EXPECT_TRUE(ozz::math::AreAllTrue3(IsNormalized(axis_angle)));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(axis_angle)));
}
TEST(Float4x4Affine, ozz_simd_math) {
EXPECT_ASSERTION(
Float4x4::FromAffine(ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 1.f),
ozz::math::simd_float4::Load(1.f, 1.f, 1.f, 1.f)),
"IsNormalized");
const Float4x4 identity =
Float4x4::FromAffine(ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f),
ozz::math::simd_float4::Load(1.f, 1.f, 1.f, 1.f));
EXPECT_FLOAT4x4_EQ(identity, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f,
1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
const Float4x4 affine = Float4x4::FromAffine(
ozz::math::simd_float4::Load(-12.f, 46.f, 12.f, 9.f),
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, .70710677f),
ozz::math::simd_float4::Load(2.f, 46.f, 3.f, 1.f));
EXPECT_FLOAT4x4_EQ(affine, 0.f, 0.f, -2.f, 0.f, 0.f, 46.f, 0.f, 0.f, 3.f, 0.f,
0.f, 0.f, -12.f, 46.f, 12.f, 1.f);
EXPECT_FALSE(ozz::math::AreAllTrue3(IsNormalized(affine)));
EXPECT_TRUE(ozz::math::AreAllTrue1(IsOrthogonal(affine)));
const Float4x4 affine_reflexion = Float4x4::FromAffine(
ozz::math::simd_float4::Load(-12.f, 46.f, 12.f, 9.f),
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, .70710677f),
ozz::math::simd_float4::Load(2.f, -1.f, 3.f, 1.f));
EXPECT_FLOAT4x4_EQ(affine_reflexion, 0.f, 0.f, -2.f, 0.f, 0.f, -1.f, 0.f, 0.f,
3.f, 0.f, 0.f, 0.f, -12.f, 46.f, 12.f, 1.f);
EXPECT_FALSE(ozz::math::AreAllTrue3(IsNormalized(affine_reflexion)));
EXPECT_FALSE(ozz::math::AreAllTrue1(IsOrthogonal(affine_reflexion)));
}
TEST(Float4x4ToQuaternion, ozz_simd_math) {
#ifndef NDEBUG
const Float4x4 not_normalized = {
{ozz::math::simd_float4::Load(1.1f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
const Float4x4 not_orthogonal = {
{ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
#endif // NDEBUG
EXPECT_ASSERTION(ToQuaternion(not_normalized), "IsNormalized");
EXPECT_ASSERTION(ToQuaternion(not_orthogonal), "IsOrthogonal");
EXPECT_SIMDFLOAT_EQ(ToQuaternion(Float4x4::identity()), 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(ToQuaternion(Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f))),
0.f, 0.f, 1.f, 0.f);
EXPECT_SIMDFLOAT_EQ(ToQuaternion(Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f))),
0.f, 1.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(ToQuaternion(Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f))),
1.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(
ToQuaternion(Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, .70710677f))),
.70710677f, 0.f, 0.f, .70710677f);
EXPECT_SIMDFLOAT_EQ(
ToQuaternion(Float4x4::FromQuaternion(ozz::math::simd_float4::Load(
.4365425f, .017589169f, -.30435428f, .84645736f))),
.4365425f, .017589169f, -.30435428f, .84645736f);
EXPECT_SIMDFLOAT_EQ(
ToQuaternion(Float4x4::FromQuaternion(ozz::math::simd_float4::Load(
.56098551f, -.092295974f, 0.43045932f, .70105737f))),
.56098551f, -.092295974f, 0.43045932f, .70105737f);
EXPECT_SIMDFLOAT_EQ(
ToQuaternion(Float4x4::FromQuaternion(ozz::math::simd_float4::Load(
-.6172133f, -.1543033f, 0.f, .7715167f))),
-.6172133f, -.1543033f, 0.f, .7715167f);
}
TEST(Float4x4ToAffine, ozz_simd_math) {
SimdFloat4 translate = ozz::math::simd_float4::zero();
SimdFloat4 rotate = ozz::math::simd_float4::zero();
SimdFloat4 scale = ozz::math::simd_float4::zero();
EXPECT_FALSE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_FALSE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_FALSE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_TRUE(ToAffine(Float4x4::identity(), &translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 1.f, 1.f, 1.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(0.f, 1.f, 1.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 0.f, 1.f, 1.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, 0.f, 1.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 1.f, 0.f, 1.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(1.f, 1.f, 0.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 1.f, 1.f, 0.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, 69.f, 58.f, 1.f)) *
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, 3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 46.f, 69.f, 58.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, 3.f, 4.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, -69.f, -58.f, 1.f)) *
Float4x4::Scaling(ozz::math::simd_float4::Load(-2.f, 3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 46.f, -69.f, -58.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 1.f, 0.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, -3.f, 4.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, -3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, -3.f, 4.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, 3.f, -4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 1.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, -3.f, 4.f, 1.f);
// This one is not a reflexion.
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(-2.f, -3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 1.f, 0.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, 3.f, 4.f, 1.f);
// This one is not a reflexion.
EXPECT_TRUE(ToAffine(
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, -3.f, -4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 1.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, 3.f, 4.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, -69.f, -58.f, 1.f)) *
Float4x4::FromQuaternion(ozz::math::simd_float4::Load(
-.6172133f, -.1543033f, 0.f, .7715167f)) *
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, 3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 46.f, -69.f, -58.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, -.6172133f, -.1543033f, 0.f, .7715167f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, 3.f, 4.f, 1.f);
EXPECT_TRUE(ToAffine(
Float4x4::Translation(
ozz::math::simd_float4::Load(46.f, -69.f, -58.f, 1.f)) *
Float4x4::FromQuaternion(
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, .70710677f)) *
Float4x4::Scaling(ozz::math::simd_float4::Load(2.f, -3.f, 4.f, 0.f)),
&translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 46.f, -69.f, -58.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, .70710677f, 0.f, 0.f, .70710677f);
EXPECT_SIMDFLOAT_EQ(scale, 2.f, -3.f, 4.f, 1.f);
const Float4x4 trace = {
{ozz::math::simd_float4::Load(-.916972f, 0.f, -.398952f, 0.f),
ozz::math::simd_float4::Load(0.f, -1, 0.f, 0.f),
ozz::math::simd_float4::Load(-.398952f, 0, .916972f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 1.f)}};
EXPECT_TRUE(ToAffine(trace, &translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(rotate, -.20375007f, 0.f, .97902298f, 0.f);
EXPECT_SIMDFLOAT_EQ(scale, 1.f, 1.f, 1.f, 1.f);
const Float4x4 small = {
{ozz::math::simd_float4::Load(.000907520065f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, .000959928846f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, .0159599986f, 0.f),
ozz::math::simd_float4::Load(.00649994006f, .00719946623f,
-.000424541620f, .999999940f)}};
EXPECT_TRUE(ToAffine(small, &translate, &rotate, &scale));
EXPECT_SIMDFLOAT_EQ(translate, .00649994006f, .00719946623f, -.000424541620f,
1.f);
EXPECT_SIMDFLOAT_EQ(rotate, 0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(scale, .000907520065f, .000959928846f, .0159599986f, 1.f);
}
@@ -0,0 +1,839 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_math.h"
#include <stdint.h>
#include <cmath>
#include <limits>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
using ozz::math::SimdFloat4;
using ozz::math::SimdInt4;
static_assert(sizeof(SimdFloat4) == 4 * sizeof(float),
"Expects SimdFloat4 to be the size of 4 floats.");
static_assert(alignof(SimdFloat4) == 16,
"Expects SimdFloat4 to be the size of 16 bytes.");
TEST(Name, ozz_simd_math) {
EXPECT_TRUE(ozz::math::SimdImplementationName() != nullptr);
}
TEST(LoadFloat, ozz_simd_math) {
const SimdFloat4 fX = ozz::math::simd_float4::LoadX(15.f);
EXPECT_SIMDFLOAT_EQ(fX, 15.f, 0.f, 0.f, 0.f);
const SimdFloat4 f1 = ozz::math::simd_float4::Load1(15.f);
EXPECT_SIMDFLOAT_EQ(f1, 15.f, 15.f, 15.f, 15.f);
const SimdFloat4 f4 = ozz::math::simd_float4::Load(1.f, -1.f, 2.f, -3.f);
EXPECT_SIMDFLOAT_EQ(f4, 1.f, -1.f, 2.f, -3.f);
}
TEST(LoadFloatPtr, ozz_simd_math) {
union Data {
float f[4 + 5];
char c[(4 + 5) * sizeof(float)]; // The 2nd char isn't aligned to a float.
};
const Data d_in = {{-1.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f}};
const int aligned_offset =
(16 - (reinterpret_cast<intptr_t>(d_in.f) & 0xf)) / sizeof(float);
assert(aligned_offset > 0 && aligned_offset <= 4);
EXPECT_SIMDFLOAT_EQ(ozz::math::simd_float4::LoadPtr(d_in.f + aligned_offset),
d_in.f[aligned_offset + 0], d_in.f[aligned_offset + 1],
d_in.f[aligned_offset + 2], d_in.f[aligned_offset + 3]);
EXPECT_ASSERTION(ozz::math::simd_float4::LoadPtr(d_in.f + aligned_offset - 1),
"alignment");
EXPECT_SIMDFLOAT_EQ(
ozz::math::simd_float4::LoadPtrU(d_in.f + aligned_offset + 1),
d_in.f[aligned_offset + 1], d_in.f[aligned_offset + 2],
d_in.f[aligned_offset + 3], d_in.f[aligned_offset + 4]);
EXPECT_ASSERTION(ozz::math::simd_float4::LoadPtrU(
reinterpret_cast<const float*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDFLOAT_EQ(
ozz::math::simd_float4::LoadXPtrU(d_in.f + aligned_offset + 1),
d_in.f[aligned_offset + 1], 0.f, 0.f, 0.f);
EXPECT_ASSERTION(ozz::math::simd_float4::LoadXPtrU(
reinterpret_cast<const float*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDFLOAT_EQ(
ozz::math::simd_float4::Load1PtrU(d_in.f + aligned_offset + 1),
d_in.f[aligned_offset + 1], d_in.f[aligned_offset + 1],
d_in.f[aligned_offset + 1], d_in.f[aligned_offset + 1]);
EXPECT_ASSERTION(ozz::math::simd_float4::Load1PtrU(
reinterpret_cast<const float*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDFLOAT_EQ(
ozz::math::simd_float4::Load2PtrU(d_in.f + aligned_offset + 1),
d_in.f[aligned_offset + 1], d_in.f[aligned_offset + 2], 0.f, 0.f);
EXPECT_ASSERTION(ozz::math::simd_float4::Load2PtrU(
reinterpret_cast<const float*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDFLOAT_EQ(
ozz::math::simd_float4::Load3PtrU(d_in.f + aligned_offset + 1),
d_in.f[aligned_offset + 1], d_in.f[aligned_offset + 2],
d_in.f[aligned_offset + 3], 0.f);
EXPECT_ASSERTION(ozz::math::simd_float4::Load3PtrU(
reinterpret_cast<const float*>(d_in.c + 1)),
"alignment");
}
TEST(GetFloat, ozz_simd_math) {
const SimdFloat4 f = ozz::math::simd_float4::Load(1.f, 2.f, 3.f, 4.f);
EXPECT_FLOAT_EQ(ozz::math::GetX(f), 1.f);
EXPECT_FLOAT_EQ(ozz::math::GetY(f), 2.f);
EXPECT_FLOAT_EQ(ozz::math::GetZ(f), 3.f);
EXPECT_FLOAT_EQ(ozz::math::GetW(f), 4.f);
}
TEST(SetFloat, ozz_simd_math) {
const SimdFloat4 a = ozz::math::simd_float4::Load(1.f, 2.f, 3.f, 4.f);
const SimdFloat4 b = ozz::math::simd_float4::Load(5.f, 6.f, 7.f, 8.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetX(a, b), 5.f, 2.f, 3.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetY(a, b), 1.f, 5.f, 3.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetZ(a, b), 1.f, 2.f, 5.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetW(a, b), 1.f, 2.f, 3.f, 5.f);
EXPECT_ASSERTION(ozz::math::SetI(a, b, 4), "Invalid index, out of range.");
EXPECT_SIMDFLOAT_EQ(ozz::math::SetI(a, b, 0), 5.f, 2.f, 3.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetI(a, b, 1), 1.f, 5.f, 3.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetI(a, b, 2), 1.f, 2.f, 5.f, 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SetI(a, b, 3), 1.f, 2.f, 3.f, 5.f);
}
TEST(StoreFloatPtr, ozz_simd_math) {
const SimdFloat4 f4 = ozz::math::simd_float4::Load(-1.f, 1.f, 2.f, 3.f);
union Data {
float f[4 + 4]; // The 2nd float isn't aligned to a SimdFloat4.
SimdFloat4 f4[2]; // Forces alignment.
char c[(4 + 4) * sizeof(float)]; // The 2nd char isn't aligned to a float.
};
{
Data d_out = {};
ozz::math::StorePtrU(f4, d_out.f + 1);
EXPECT_FLOAT_EQ(d_out.f[0], 0.f);
EXPECT_FLOAT_EQ(d_out.f[1], -1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 1.f);
EXPECT_FLOAT_EQ(d_out.f[3], 2.f);
EXPECT_FLOAT_EQ(d_out.f[4], 3.f);
EXPECT_ASSERTION(
ozz::math::StorePtrU(f4, reinterpret_cast<float*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store1PtrU(f4, d_out.f + 1);
EXPECT_FLOAT_EQ(d_out.f[0], 0.f);
EXPECT_FLOAT_EQ(d_out.f[1], -1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 0.f);
EXPECT_FLOAT_EQ(d_out.f[3], 0.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(
ozz::math::Store1PtrU(f4, reinterpret_cast<float*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store2PtrU(f4, d_out.f + 1);
EXPECT_FLOAT_EQ(d_out.f[0], 0.f);
EXPECT_FLOAT_EQ(d_out.f[1], -1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 1.f);
EXPECT_FLOAT_EQ(d_out.f[3], 0.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(
ozz::math::Store2Ptr(f4, reinterpret_cast<float*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store3PtrU(f4, d_out.f + 1);
EXPECT_FLOAT_EQ(d_out.f[0], 0.f);
EXPECT_FLOAT_EQ(d_out.f[1], -1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 1.f);
EXPECT_FLOAT_EQ(d_out.f[3], 2.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(
ozz::math::Store3Ptr(f4, reinterpret_cast<float*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::StorePtr(f4, d_out.f);
EXPECT_FLOAT_EQ(d_out.f[0], -1.f);
EXPECT_FLOAT_EQ(d_out.f[1], 1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 2.f);
EXPECT_FLOAT_EQ(d_out.f[3], 3.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(ozz::math::StorePtr(f4, d_out.f + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store1Ptr(f4, d_out.f);
EXPECT_FLOAT_EQ(d_out.f[0], -1.f);
EXPECT_FLOAT_EQ(d_out.f[1], 0.f);
EXPECT_FLOAT_EQ(d_out.f[2], 0.f);
EXPECT_FLOAT_EQ(d_out.f[3], 0.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(ozz::math::Store1Ptr(f4, d_out.f + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store2Ptr(f4, d_out.f);
EXPECT_FLOAT_EQ(d_out.f[0], -1.f);
EXPECT_FLOAT_EQ(d_out.f[1], 1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 0.f);
EXPECT_FLOAT_EQ(d_out.f[3], 0.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(ozz::math::Store2Ptr(f4, d_out.f + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store3Ptr(f4, d_out.f);
EXPECT_FLOAT_EQ(d_out.f[0], -1.f);
EXPECT_FLOAT_EQ(d_out.f[1], 1.f);
EXPECT_FLOAT_EQ(d_out.f[2], 2.f);
EXPECT_FLOAT_EQ(d_out.f[3], 0.f);
EXPECT_FLOAT_EQ(d_out.f[4], 0.f);
EXPECT_ASSERTION(ozz::math::Store3Ptr(f4, d_out.f + 1), "alignment");
}
}
TEST(ConstantFloat, ozz_simd_math) {
const SimdFloat4 zero = ozz::math::simd_float4::zero();
EXPECT_SIMDFLOAT_EQ(zero, 0.f, 0.f, 0.f, 0.f);
const SimdFloat4 one = ozz::math::simd_float4::one();
EXPECT_SIMDFLOAT_EQ(one, 1.f, 1.f, 1.f, 1.f);
const SimdFloat4 x_axis = ozz::math::simd_float4::x_axis();
EXPECT_SIMDFLOAT_EQ(x_axis, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 y_axis = ozz::math::simd_float4::y_axis();
EXPECT_SIMDFLOAT_EQ(y_axis, 0.f, 1.f, 0.f, 0.f);
const SimdFloat4 z_axis = ozz::math::simd_float4::z_axis();
EXPECT_SIMDFLOAT_EQ(z_axis, 0.f, 0.f, 1.f, 0.f);
const SimdFloat4 w_axis = ozz::math::simd_float4::w_axis();
EXPECT_SIMDFLOAT_EQ(w_axis, 0.f, 0.f, 0.f, 1.f);
}
TEST(SplatFloat, ozz_simd_math) {
const SimdFloat4 f = ozz::math::simd_float4::Load(1.f, -1.f, 2.f, -3.f);
const SimdFloat4 x = ozz::math::SplatX(f);
EXPECT_SIMDFLOAT_EQ(x, 1.f, 1.f, 1.f, 1.f);
const SimdFloat4 y = ozz::math::SplatY(f);
EXPECT_SIMDFLOAT_EQ(y, -1.f, -1.f, -1.f, -1.f);
const SimdFloat4 z = ozz::math::SplatZ(f);
EXPECT_SIMDFLOAT_EQ(z, 2.f, 2.f, 2.f, 2.f);
const SimdFloat4 w = ozz::math::SplatW(f);
EXPECT_SIMDFLOAT_EQ(w, -3.f, -3.f, -3.f, -3.f);
const SimdFloat4 s3210 = ozz::math::Swizzle<3, 2, 1, 0>(f);
EXPECT_SIMDFLOAT_EQ(s3210, -3.f, 2.f, -1.f, 1.f);
const SimdFloat4 s0123 = ozz::math::Swizzle<0, 1, 2, 3>(f);
EXPECT_SIMDFLOAT_EQ(s0123, 1.f, -1.f, 2.f, -3.f);
const SimdFloat4 s0011 = ozz::math::Swizzle<0, 0, 1, 1>(f);
EXPECT_SIMDFLOAT_EQ(s0011, 1.f, 1.f, -1.f, -1.f);
const SimdFloat4 s2233 = ozz::math::Swizzle<2, 2, 3, 3>(f);
EXPECT_SIMDFLOAT_EQ(s2233, 2.f, 2.f, -3.f, -3.f);
const SimdFloat4 s0101 = ozz::math::Swizzle<0, 1, 0, 1>(f);
EXPECT_SIMDFLOAT_EQ(s0101, 1.f, -1.f, 1.f, -1.f);
const SimdFloat4 s2323 = ozz::math::Swizzle<2, 3, 2, 3>(f);
EXPECT_SIMDFLOAT_EQ(s2323, 2.f, -3.f, 2.f, -3.f);
}
TEST(FromInt, ozz_simd_math) {
const ozz::math::SimdInt4 i = ozz::math::simd_int4::Load(0, 46, -93, 9926429);
EXPECT_SIMDFLOAT_EQ(ozz::math::simd_float4::FromInt(i), 0.f, 46.f, -93.f,
9926429.f);
}
TEST(ArithmeticFloat, ozz_simd_math) {
const ozz::math::SimdFloat4 a =
ozz::math::simd_float4::Load(0.5f, 1.f, 2.f, 3.f);
const ozz::math::SimdFloat4 b =
ozz::math::simd_float4::Load(4.f, 5.f, -6.f, 0.f);
const ozz::math::SimdFloat4 c =
ozz::math::simd_float4::Load(-8.f, 9.f, 10.f, 11.f);
const ozz::math::SimdFloat4 add = a + b;
EXPECT_SIMDFLOAT_EQ(add, 4.5f, 6.f, -4.f, 3.f);
const ozz::math::SimdFloat4 sub = a - b;
EXPECT_SIMDFLOAT_EQ(sub, -3.5f, -4.f, 8.f, 3.f);
const ozz::math::SimdFloat4 neg = -b;
EXPECT_SIMDFLOAT_EQ(neg, -4.f, -5.f, 6.f, -0.f);
const ozz::math::SimdFloat4 mul = a * b;
EXPECT_SIMDFLOAT_EQ(mul, 2.f, 5.f, -12.f, 0.f);
const ozz::math::SimdFloat4 div = a / b;
EXPECT_SIMDFLOAT3_EQ(div, 0.5f / 4.f, 1.f / 5.f, -2.f / 6.f);
const ozz::math::SimdFloat4 madd = ozz::math::MAdd(a, b, c);
EXPECT_SIMDFLOAT_EQ(madd, -6.f, 14.f, -2.f, 11.f);
const ozz::math::SimdFloat4 msub = ozz::math::MSub(a, b, c);
EXPECT_SIMDFLOAT_EQ(msub, 10.f, -4.f, -22.f, -11.f);
const ozz::math::SimdFloat4 nmadd = ozz::math::NMAdd(a, b, c);
EXPECT_SIMDFLOAT_EQ(nmadd, -10.f, 4.f, 22.f, 11.f);
const ozz::math::SimdFloat4 nmsub = ozz::math::NMSub(a, b, c);
EXPECT_SIMDFLOAT_EQ(nmsub, 6.f, -14.f, 2.f, -11.f);
const ozz::math::SimdFloat4 divx = ozz::math::DivX(a, b);
EXPECT_SIMDFLOAT_EQ(divx, 0.5f / 4.f, 1.f, 2.f, 3.f);
const ozz::math::SimdFloat4 hadd2 = ozz::math::HAdd2(a);
EXPECT_SIMDFLOAT_EQ(hadd2, 1.5f, 1.f, 2.f, 3.f);
const ozz::math::SimdFloat4 hadd3 = ozz::math::HAdd3(a);
EXPECT_SIMDFLOAT_EQ(hadd3, 3.5f, 1.f, 2.f, 3.f);
const ozz::math::SimdFloat4 hadd4 = ozz::math::HAdd4(a);
EXPECT_FLOAT_EQ(ozz::math::GetX(hadd4), 6.5f);
const ozz::math::SimdFloat4 dot2 = ozz::math::Dot2(a, b);
EXPECT_FLOAT_EQ(ozz::math::GetX(dot2), 7.f);
const ozz::math::SimdFloat4 dot3 = ozz::math::Dot3(a, b);
EXPECT_FLOAT_EQ(ozz::math::GetX(dot3), -5.f);
const ozz::math::SimdFloat4 dot4 = ozz::math::Dot4(a, b);
EXPECT_FLOAT_EQ(ozz::math::GetX(dot4), -5.f);
const ozz::math::SimdFloat4 cross =
ozz::math::Cross3(ozz::math::simd_float4::Load(1.f, -2.f, 3.f, 46.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 27.f));
EXPECT_FLOAT_EQ(ozz::math::GetX(cross), -27.f);
EXPECT_FLOAT_EQ(ozz::math::GetY(cross), 6.f);
EXPECT_FLOAT_EQ(ozz::math::GetZ(cross), 13.f);
const ozz::math::SimdFloat4 rcp = ozz::math::RcpEst(b);
EXPECT_SIMDFLOAT3_EQ_EST(rcp, 1.f / 4.f, 1.f / 5.f, -1.f / 6.f);
const ozz::math::SimdFloat4 rcpnr = ozz::math::RcpEstNR(b);
EXPECT_SIMDFLOAT3_EQ(rcpnr, 1.f / 4.f, 1.f / 5.f, -1.f / 6.f);
const ozz::math::SimdFloat4 rcpxnr = ozz::math::RcpEstXNR(b);
EXPECT_FLOAT_EQ(ozz::math::GetX(rcpxnr), 1.f / 4.f);
const ozz::math::SimdFloat4 rcpx = ozz::math::RcpEstX(b);
EXPECT_SIMDFLOAT_EQ_EST(rcpx, 1.f / 4.f, 5.f, -6.f, 0.f);
const ozz::math::SimdFloat4 sqrt = ozz::math::Sqrt(a);
EXPECT_SIMDFLOAT_EQ(sqrt, .7071068f, 1.f, 1.4142135f, 1.7320508f);
const ozz::math::SimdFloat4 sqrtx = ozz::math::SqrtX(b);
EXPECT_SIMDFLOAT_EQ(sqrtx, 2.f, 5.f, -6.f, 0.f);
const ozz::math::SimdFloat4 rsqrt = ozz::math::RSqrtEst(b);
EXPECT_SIMDFLOAT2_EQ_EST(rsqrt, 1.f / 2.f, 1.f / 2.23606798f);
const ozz::math::SimdFloat4 rsqrtnr = ozz::math::RSqrtEstNR(b);
EXPECT_SIMDFLOAT2_EQ_EST(rsqrtnr, 1.f / 2.f, 1.f / 2.23606798f);
const ozz::math::SimdFloat4 rsqrtx = ozz::math::RSqrtEstX(a);
EXPECT_SIMDFLOAT_EQ_EST(rsqrtx, 1.f / .7071068f, 1.f, 2.f, 3.f);
const ozz::math::SimdFloat4 rsqrtxnr = ozz::math::RSqrtEstXNR(a);
EXPECT_FLOAT_EQ(ozz::math::GetX(rsqrtxnr), 1.f / .7071068f);
const ozz::math::SimdFloat4 abs = ozz::math::Abs(b);
EXPECT_SIMDFLOAT_EQ(abs, 4.f, 5.f, 6.f, 0.f);
const SimdInt4 sign = ozz::math::Sign(b);
EXPECT_SIMDINT_EQ(sign, 0, 0, 0x80000000, 0);
}
TEST(LengthFloat, ozz_simd_math) {
const SimdFloat4 f = ozz::math::simd_float4::Load(1.f, 2.f, 4.f, 8.f);
const SimdFloat4 len2 = ozz::math::Length2(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len2), 2.236068f);
const SimdFloat4 len3 = ozz::math::Length3(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len3), 4.5825758f);
const SimdFloat4 len4 = ozz::math::Length4(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len4), 9.2195444f);
const SimdFloat4 len2sqr = ozz::math::Length2Sqr(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len2sqr), 5.f);
const SimdFloat4 len3sqr = ozz::math::Length3Sqr(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len3sqr), 21.f);
const SimdFloat4 len4sqr = ozz::math::Length4Sqr(f);
EXPECT_FLOAT_EQ(ozz::math::GetX(len4sqr), 85.f);
}
TEST(NormalizeFloat, ozz_simd_math) {
const SimdFloat4 f = ozz::math::simd_float4::Load(1.f, 2.f, 4.f, 8.f);
const SimdFloat4 unit = ozz::math::simd_float4::x_axis();
const SimdFloat4 zero = ozz::math::simd_float4::zero();
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized2(f), 0, 0, 0, 0);
const SimdFloat4 norm2 = ozz::math::Normalize2(f);
EXPECT_SIMDFLOAT_EQ(norm2, .44721359f, .89442718f, 4.f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized2(norm2), 0xffffffff, 0, 0, 0);
const SimdFloat4 norm_est2 = ozz::math::NormalizeEst2(f);
EXPECT_SIMDFLOAT_EQ_EST(norm_est2, .44721359f, .89442718f, 4.f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst2(norm_est2), 0xffffffff, 0, 0,
0);
EXPECT_ASSERTION(ozz::math::Normalize2(zero), "_v is not normalizable");
EXPECT_ASSERTION(ozz::math::NormalizeEst2(zero), "_v is not normalizable");
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized3(f), 0, 0, 0, 0);
const SimdFloat4 norm3 = ozz::math::Normalize3(f);
EXPECT_SIMDFLOAT_EQ(norm3, .21821788f, .43643576f, .87287152f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized3(norm3), 0xffffffff, 0, 0, 0);
const SimdFloat4 norm_est3 = ozz::math::NormalizeEst3(f);
EXPECT_SIMDFLOAT_EQ_EST(norm_est3, .21821788f, .43643576f, .87287152f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst3(norm_est3), 0xffffffff, 0, 0,
0);
EXPECT_ASSERTION(ozz::math::Normalize3(zero), "_v is not normalizable");
EXPECT_ASSERTION(ozz::math::NormalizeEst3(zero), "_v is not normalizable");
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized4(f), 0, 0, 0, 0);
const SimdFloat4 norm4 = ozz::math::Normalize4(f);
EXPECT_SIMDFLOAT_EQ(norm4, .1084652f, .2169304f, .4338609f, .86772186f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized4(norm4), 0xffffffff, 0, 0, 0);
const SimdFloat4 norm_est4 = ozz::math::NormalizeEst4(f);
EXPECT_SIMDFLOAT_EQ_EST(norm_est4, .1084652f, .2169304f, .4338609f,
.86772186f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst4(norm_est4), 0xffffffff, 0, 0,
0);
EXPECT_ASSERTION(ozz::math::Normalize4(zero), "_v is not normalizable");
EXPECT_ASSERTION(ozz::math::NormalizeEst4(zero), "_v is not normalizable");
const SimdFloat4 safe2 = ozz::math::NormalizeSafe2(f, unit);
EXPECT_SIMDFLOAT_EQ(safe2, .4472136f, .8944272f, 4.f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized2(safe2), 0xffffffff, 0, 0, 0);
const SimdFloat4 safer2 = ozz::math::NormalizeSafe2(zero, unit);
EXPECT_SIMDFLOAT_EQ(safer2, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 safe_est2 = ozz::math::NormalizeSafeEst2(f, unit);
EXPECT_SIMDFLOAT_EQ_EST(safe_est2, .4472136f, .8944272f, 4.f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst2(safe_est2), 0xffffffff, 0, 0,
0);
const SimdFloat4 safer_est2 = ozz::math::NormalizeSafeEst2(zero, unit);
EXPECT_SIMDFLOAT_EQ_EST(safer_est2, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 safe3 = ozz::math::NormalizeSafe3(f, unit);
EXPECT_SIMDFLOAT_EQ(safe3, .21821788f, .43643576f, .87287152f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized3(safe3), 0xffffffff, 0, 0, 0);
const SimdFloat4 safer3 = ozz::math::NormalizeSafe3(zero, unit);
EXPECT_SIMDFLOAT_EQ(safer3, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 safe_est3 = ozz::math::NormalizeSafeEst3(f, unit);
EXPECT_SIMDFLOAT_EQ_EST(safe_est3, .21821788f, .43643576f, .87287152f, 8.f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst3(safe_est3), 0xffffffff, 0, 0,
0);
const SimdFloat4 safer_est3 = ozz::math::NormalizeSafeEst3(zero, unit);
EXPECT_SIMDFLOAT_EQ_EST(safer_est3, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 safe4 = ozz::math::NormalizeSafe4(f, unit);
EXPECT_SIMDFLOAT_EQ(safe4, .1084652f, .2169305f, .433861f, .8677219f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized4(safe4), 0xffffffff, 0, 0, 0);
const SimdFloat4 safer4 = ozz::math::NormalizeSafe4(zero, unit);
EXPECT_SIMDFLOAT_EQ(safer4, 1.f, 0.f, 0.f, 0.f);
const SimdFloat4 safe_est4 = ozz::math::NormalizeSafeEst4(f, unit);
EXPECT_SIMDFLOAT_EQ_EST(safe_est4, .1084652f, .2169305f, .433861f, .8677219f);
EXPECT_SIMDINT_EQ(ozz::math::IsNormalizedEst4(safe_est4), 0xffffffff, 0, 0,
0);
const SimdFloat4 safer_est4 = ozz::math::NormalizeSafeEst4(zero, unit);
EXPECT_SIMDFLOAT_EQ_EST(safer_est4, 1.f, 0.f, 0.f, 0.f);
}
TEST(CompareFloat, ozz_simd_math) {
const SimdFloat4 a = ozz::math::simd_float4::Load(0.5f, 1.f, 2.f, 3.f);
const SimdFloat4 b = ozz::math::simd_float4::Load(4.f, 1.f, -6.f, 7.f);
const SimdFloat4 c = ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f);
const SimdFloat4 min = ozz::math::Min(a, b);
EXPECT_SIMDFLOAT_EQ(min, 0.5f, 1.f, -6.f, 3.f);
const SimdFloat4 max = ozz::math::Max(a, b);
EXPECT_SIMDFLOAT_EQ(max, 4.f, 1.f, 2.f, 7.f);
const SimdFloat4 min0 = ozz::math::Min0(b);
EXPECT_SIMDFLOAT_EQ(min0, 0.f, 0.f, -6.f, 0.f);
const SimdFloat4 max0 = ozz::math::Max0(b);
EXPECT_SIMDFLOAT_EQ(max0, 4.f, 1.f, 0.f, 7.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Clamp(a, ozz::math::simd_float4::Load(-12.f, 2.f, 9.f, 3.f),
c),
.5f, 2.f, 6.f, 3.f);
const SimdInt4 eq1 = ozz::math::CmpEq(a, b);
EXPECT_SIMDINT_EQ(eq1, 0, 0xffffffff, 0, 0);
const SimdInt4 eq2 = ozz::math::CmpEq(a, a);
EXPECT_SIMDINT_EQ(eq2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
const SimdInt4 neq1 = ozz::math::CmpNe(a, b);
EXPECT_SIMDINT_EQ(neq1, 0xffffffff, 0, 0xffffffff, 0xffffffff);
const SimdInt4 neq2 = ozz::math::CmpNe(a, a);
EXPECT_SIMDINT_EQ(neq2, 0, 0, 0, 0);
const SimdInt4 lt = ozz::math::CmpLt(a, b);
EXPECT_SIMDINT_EQ(lt, 0xffffffff, 0, 0, 0xffffffff);
const SimdInt4 le = ozz::math::CmpLe(a, b);
EXPECT_SIMDINT_EQ(le, 0xffffffff, 0xffffffff, 0u, 0xffffffff);
const SimdInt4 gt = ozz::math::CmpGt(a, b);
EXPECT_SIMDINT_EQ(gt, 0u, 0u, 0xffffffff, 0u);
const SimdInt4 ge = ozz::math::CmpGe(a, b);
EXPECT_SIMDINT_EQ(ge, 0u, 0xffffffff, 0xffffffff, 0u);
}
TEST(LerpFloat, ozz_simd_math) {
const SimdFloat4 a = ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 4.f);
const SimdFloat4 b = ozz::math::simd_float4::Load(0.f, -1.f, -2.f, -4.f);
const SimdFloat4 zero = ozz::math::simd_float4::Load1(0.f);
const SimdFloat4 one = ozz::math::simd_float4::Load1(1.f);
const SimdFloat4 lerp0 = ozz::math::Lerp(a, b, zero);
EXPECT_SIMDFLOAT_EQ(lerp0, 0.f, 1.f, 2.f, 4.f);
const SimdFloat4 lerp1 = ozz::math::Lerp(a, b, one);
EXPECT_SIMDFLOAT_EQ(lerp1, 0.f, -1.f, -2.f, -4.f);
const SimdFloat4 lhalf =
ozz::math::Lerp(a, b, ozz::math::simd_float4::Load1(0.5f));
EXPECT_SIMDFLOAT_EQ(lhalf, 0.f, 0.f, 0.f, 0.f);
const SimdFloat4 lmixed =
ozz::math::Lerp(a, b, ozz::math::simd_float4::Load(0.f, -1.f, 0.5f, 2.f));
EXPECT_SIMDFLOAT_EQ(lmixed, 0.f, 3.f, 0.f, -12.f);
}
TEST(TrigonometryFloat, ozz_simd_math) {
using ozz::math::k2Pi;
using ozz::math::kPi;
using ozz::math::kPi_2;
const SimdFloat4 angle =
ozz::math::simd_float4::Load(kPi, kPi / 6.f, -kPi_2, 5.f * kPi_2);
const SimdFloat4 cos =
ozz::math::simd_float4::Load(-1.f, .86602539f, 0.f, 0.f);
const SimdFloat4 sin = ozz::math::simd_float4::Load(0.f, .5f, -1.f, 1.f);
const SimdFloat4 angle_tan =
ozz::math::simd_float4::Load(0.f, kPi / 6.f, -kPi / 3.f, 9.f * kPi / 4.f);
const SimdFloat4 tan =
ozz::math::simd_float4::Load(0.f, .57735f, -1.73205f, 1.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::Cos(angle), -1.f, .86602539f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Cos(angle + ozz::math::simd_float4::Load1(k2Pi)), -1.f,
.86602539f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Cos(angle + ozz::math::simd_float4::Load1(k2Pi * 12.f)), -1.f,
.86602539f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Cos(angle - ozz::math::simd_float4::Load1(k2Pi * 24.f)), -1.f,
.86602539f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::CosX(angle), -1.f, kPi / 6.f, -kPi_2,
5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::CosX(angle + ozz::math::simd_float4::LoadX(k2Pi)), -1.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::CosX(angle + ozz::math::simd_float4::LoadX(k2Pi * 12.f)), -1.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::CosX(angle - ozz::math::simd_float4::LoadX(k2Pi * 24.f)), -1.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(ozz::math::Sin(angle), 0.f, .5f, -1.f, 1.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Sin(angle + ozz::math::simd_float4::Load1(k2Pi)), 0.f, 0.5f,
-1.f, 1.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Sin(angle + ozz::math::simd_float4::Load1(k2Pi * 12.f)), 0.f,
.5f, -1.f, 1.f);
EXPECT_SIMDFLOAT_EQ(
ozz::math::Sin(angle - ozz::math::simd_float4::Load1(k2Pi * 24.f)), 0.f,
.5f, -1.f, 1.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::SinX(angle), 0.f, kPi / 6.f, -kPi_2,
5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::SinX(angle + ozz::math::simd_float4::LoadX(k2Pi)), 0.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::SinX(angle + ozz::math::simd_float4::LoadX(k2Pi * 12.f)), 0.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(
ozz::math::SinX(angle - ozz::math::simd_float4::LoadX(k2Pi * 24.f)), 0.f,
kPi / 6.f, -kPi_2, 5.f * kPi_2);
EXPECT_SIMDFLOAT_EQ(ozz::math::ACos(cos), kPi, kPi / 6.f, kPi_2, kPi_2);
EXPECT_SIMDFLOAT_EQ(ozz::math::ACosX(cos), kPi, .86602539f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::ASin(sin), 0.f, kPi / 6.f, -kPi_2, kPi_2);
EXPECT_SIMDFLOAT_EQ(ozz::math::ASinX(sin), 0.f, .5f, -1.f, 1.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::Tan(angle_tan), 0.f, 0.57735f, -1.73205f, 1.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::TanX(angle_tan), 0.f, kPi / 6.f, -kPi / 3.f,
9.f * kPi / 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::ATan(tan), 0.f, kPi / 6.f, -kPi / 3.f,
kPi / 4.f);
EXPECT_SIMDFLOAT_EQ(ozz::math::ATanX(tan), 0.f, .57735f, -1.73205f, 1.f);
}
TEST(LogicalFloat, ozz_simd_math) {
const SimdFloat4 a = ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f);
const SimdFloat4 b = ozz::math::simd_float4::Load(1.f, -1.f, -3.f, -4.f);
const SimdInt4 mbool =
ozz::math::simd_int4::Load(0xffffffff, 0, 0, 0xffffffff);
const SimdInt4 mbit =
ozz::math::simd_int4::Load(0xffffffff, 0, 0x80000000, 0x7fffffff);
const SimdFloat4 mfloat = ozz::math::simd_float4::Load(1.f, 0.f, -0.f, 3.f);
const SimdFloat4 select = ozz::math::Select(mbool, a, b);
EXPECT_SIMDFLOAT_EQ(select, 0.f, -1.f, -3.f, 3.f);
const SimdFloat4 andm = ozz::math::And(b, mbit);
EXPECT_SIMDFLOAT_EQ(andm, 1.f, 0.f, 0.f, 4.f);
const SimdFloat4 andnm = ozz::math::AndNot(b, mbit);
EXPECT_SIMDFLOAT_EQ(andnm, 0.f, -1.f, 3.f, -0.f);
const SimdFloat4 andf = ozz::math::And(b, mfloat);
EXPECT_SIMDFLOAT_EQ(andf, 1.f, 0.f, -0.f, 2.f);
const SimdFloat4 orm = ozz::math::Or(a, mbit);
union {
float f;
unsigned int i;
} orx = {ozz::math::GetX(orm)};
EXPECT_EQ(orx.i, 0xffffffff);
EXPECT_FLOAT_EQ(ozz::math::GetY(orm), 1.f);
EXPECT_FLOAT_EQ(ozz::math::GetZ(orm), -2.f);
union {
float f;
int i;
} orw = {ozz::math::GetW(orm)};
EXPECT_TRUE(orw.i == 0x7fffffff);
const SimdFloat4 ormf = ozz::math::Or(a, mfloat);
EXPECT_SIMDFLOAT_EQ(ormf, 1.f, 1.f, -2.f, 3.f);
const SimdFloat4 xorm = ozz::math::Xor(a, mbit);
union {
float f;
unsigned int i;
} xorx = {ozz::math::GetX(xorm)};
EXPECT_TRUE(xorx.i == 0xffffffff);
EXPECT_FLOAT_EQ(ozz::math::GetY(xorm), 1.f);
EXPECT_FLOAT_EQ(ozz::math::GetZ(xorm), -2.f);
union {
float f;
unsigned int i;
} xorw = {ozz::math::GetW(xorm)};
EXPECT_TRUE(xorw.i == 0x3fbfffff);
const SimdFloat4 xormf = ozz::math::Xor(a, mfloat);
EXPECT_SIMDFLOAT_EQ(xormf, 1.f, 1.f, -2.f, 0.f);
}
TEST(Half, ozz_simd_math) {
// 0
EXPECT_EQ(ozz::math::FloatToHalf(0.f), 0);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0), 0.f);
EXPECT_EQ(ozz::math::FloatToHalf(-0.f), 0x8000);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0x8000), -0.f);
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::min()), 0);
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::denorm_min()),
0);
EXPECT_EQ(
ozz::math::FloatToHalf(std::numeric_limits<float>::denorm_min() / 10.f),
0);
// 1
EXPECT_EQ(ozz::math::FloatToHalf(1.f), 0x3c00);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0x3c00), 1.f);
EXPECT_EQ(ozz::math::FloatToHalf(-1.f), 0xbc00);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0xbc00), -1.f);
// Bounds
EXPECT_EQ(ozz::math::FloatToHalf(65504.f), 0x7bff);
EXPECT_EQ(ozz::math::FloatToHalf(-65504.f), 0xfbff);
// Min, Max, Infinity
EXPECT_EQ(ozz::math::FloatToHalf(10e-16f), 0);
EXPECT_EQ(ozz::math::FloatToHalf(10e+16f), 0x7c00);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0x7c00),
std::numeric_limits<float>::infinity());
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::max()), 0x7c00);
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::infinity()),
0x7c00);
EXPECT_EQ(ozz::math::FloatToHalf(-10e+16f), 0xfc00);
EXPECT_EQ(ozz::math::FloatToHalf(-std::numeric_limits<float>::infinity()),
0xfc00);
EXPECT_EQ(ozz::math::FloatToHalf(-std::numeric_limits<float>::max()), 0xfc00);
EXPECT_FLOAT_EQ(ozz::math::HalfToFloat(0xfc00),
-std::numeric_limits<float>::infinity());
// Nan
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::quiet_NaN()),
0x7e00);
EXPECT_EQ(ozz::math::FloatToHalf(std::numeric_limits<float>::signaling_NaN()),
0x7e00);
// According to the IEEE standard, NaN values have the odd property that
// comparisons involving them are always false
EXPECT_FALSE(ozz::math::HalfToFloat(0x7e00) ==
ozz::math::HalfToFloat(0x7e00));
// Random tries in range [10e-4,10e4].
for (float pow = -4.f; pow <= 4.f; pow += 1.f) {
const float max = powf(10.f, pow);
// Expect a 1/1000 precision over floats.
const float precision = max / 1000.f;
const int n = 1000;
for (int i = 0; i < n; ++i) {
const float frand = max * (2.f * i / n - 1.f);
const uint16_t h = ozz::math::FloatToHalf(frand);
const float f = ozz::math::HalfToFloat(h);
EXPECT_NEAR(frand, f, precision);
}
}
}
TEST(SimdHalf, ozz_simd_math) {
// 0
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(ozz::math::simd_float4::Load(
0.f, -0.f, std::numeric_limits<float>::min(),
std::numeric_limits<float>::denorm_min())),
0, 0x00008000, 0, 0);
EXPECT_SIMDFLOAT_EQ(
ozz::math::HalfToFloat(ozz::math::simd_int4::Load(0, 0x00008000, 0, 0)),
0.f, -0.f, 0.f, 0.f);
// 1
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(
ozz::math::simd_float4::Load(1.f, -1.f, 0.f, -0.f)),
0x00003c00, 0x0000bc00, 0, 0x00008000);
EXPECT_SIMDFLOAT_EQ(ozz::math::HalfToFloat(ozz::math::simd_int4::Load(
0x3c00, 0xbc00, 0, 0x00008000)),
1.f, -1.f, 0.f, -0.f);
// Bounds
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(ozz::math::simd_float4::Load(
65504.f, -65504.f, 65604.f, -65604.f)),
0x00007bff, 0x0000fbff, 0x00007c00, 0x0000fc00);
// Min, Max, Infinity
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(ozz::math::simd_float4::Load(
10e-16f, 10e+16f, std::numeric_limits<float>::max(),
std::numeric_limits<float>::infinity())),
0, 0x00007c00, 0x00007c00, 0x00007c00);
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(ozz::math::simd_float4::Load(
-10e-16f, -10e+16f, -std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max())),
0x00008000, 0x0000fc00, 0x0000fc00, 0x0000fc00);
// Nan
EXPECT_SIMDINT_EQ(ozz::math::FloatToHalf(ozz::math::simd_float4::Load(
std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::signaling_NaN(), 0, 0)),
0x00007e00, 0x00007e00, 0, 0);
// Inf and NAN
const SimdFloat4 infnan = ozz::math::HalfToFloat(
ozz::math::simd_int4::Load(0x00007c00, 0x0000fc00, 0x00007e00, 0));
EXPECT_FLOAT_EQ(ozz::math::GetX(infnan),
std::numeric_limits<float>::infinity());
EXPECT_FLOAT_EQ(ozz::math::GetY(infnan),
-std::numeric_limits<float>::infinity());
EXPECT_FALSE(ozz::math::GetZ(infnan) == ozz::math::GetZ(infnan));
// Random tries in range [10e-4,10e4].
srand(0);
for (float pow = -4.f; pow <= 4.f; pow += 1.f) {
const float max = powf(10.f, pow);
// Expect a 1/1000 precision over floats.
const float precision = max / 1000.f;
const int n = 1000;
for (int i = 0; i < n; ++i) {
const SimdFloat4 frand = ozz::math::simd_float4::Load(
max * (.5f * i / n - .25f), max * (1.f * i / n - .5f),
max * (1.5f * i / n - .75f), max * (2.f * i / n - 1.f));
const SimdInt4 h = ozz::math::FloatToHalf(frand);
const SimdFloat4 f = ozz::math::HalfToFloat(h);
EXPECT_NEAR(ozz::math::GetX(frand), ozz::math::GetX(f), precision);
EXPECT_NEAR(ozz::math::GetY(frand), ozz::math::GetY(f), precision);
EXPECT_NEAR(ozz::math::GetZ(frand), ozz::math::GetZ(f), precision);
EXPECT_NEAR(ozz::math::GetW(frand), ozz::math::GetW(f), precision);
}
}
}
@@ -0,0 +1,524 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_math.h"
#include <stdint.h>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
using ozz::math::SimdInt4;
static_assert(sizeof(SimdInt4) == 4 * sizeof(int32_t),
"Expects SimdInt4 to be the size of 4 int32_t.");
static_assert(alignof(SimdInt4) == 16,
"Expects SimdInt4 to be the size of 16 bytes.");
TEST(LoadInt, ozz_simd_math) {
const SimdInt4 iX = ozz::math::simd_int4::LoadX(15);
EXPECT_SIMDINT_EQ(iX, 15, 0, 0, 0);
const SimdInt4 i1 = ozz::math::simd_int4::Load1(15);
EXPECT_SIMDINT_EQ(i1, 15, 15, 15, 15);
const SimdInt4 i4 = ozz::math::simd_int4::Load(1, -1, 2, -3);
EXPECT_SIMDINT_EQ(i4, 1, -1, 2, -3);
const SimdInt4 itX = ozz::math::simd_int4::LoadX(true);
EXPECT_SIMDINT_EQ(itX, 0xffffffff, 0, 0, 0);
const SimdInt4 ifX = ozz::math::simd_int4::LoadX(false);
EXPECT_SIMDINT_EQ(ifX, 0, 0, 0, 0);
const SimdInt4 it1 = ozz::math::simd_int4::Load1(true);
EXPECT_SIMDINT_EQ(it1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
const SimdInt4 if1 = ozz::math::simd_int4::Load1(false);
EXPECT_SIMDINT_EQ(if1, 0, 0, 0, 0);
const SimdInt4 ibttff = ozz::math::simd_int4::Load(true, true, false, false);
EXPECT_SIMDINT_EQ(ibttff, 0xffffffff, 0xffffffff, 0, 0);
const SimdInt4 ibftft = ozz::math::simd_int4::Load(false, true, false, true);
EXPECT_SIMDINT_EQ(ibftft, 0, 0xffffffff, 0, 0xffffffff);
}
TEST(LoadIntPtr, ozz_simd_math) {
union Data {
int i[4 + 5];
char c[(4 + 5) * sizeof(int)]; // The 2nd char isn't aligned to an integer.
};
const Data d_in = {{-1, 1, 2, 3, 4, 5, 6, 7, 8}};
const int aligned_offset =
(16 - (reinterpret_cast<intptr_t>(d_in.i) & 0xf)) / sizeof(float);
assert(aligned_offset > 0 && aligned_offset <= 4);
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::LoadPtrU(d_in.i + aligned_offset + 1),
d_in.i[aligned_offset + 1], d_in.i[aligned_offset + 2],
d_in.i[aligned_offset + 3], d_in.i[aligned_offset + 4]);
EXPECT_ASSERTION(
ozz::math::simd_int4::LoadPtrU(reinterpret_cast<const int*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::LoadPtr(d_in.i + aligned_offset),
d_in.i[aligned_offset], d_in.i[aligned_offset + 1],
d_in.i[aligned_offset + 2], d_in.i[aligned_offset + 3]);
EXPECT_ASSERTION(ozz::math::simd_int4::LoadPtr(d_in.i + aligned_offset + 1),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::LoadXPtrU(d_in.i + aligned_offset),
d_in.i[aligned_offset], 0, 0, 0);
EXPECT_ASSERTION(
ozz::math::simd_int4::LoadXPtrU(reinterpret_cast<const int*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::Load1PtrU(d_in.i + aligned_offset),
d_in.i[aligned_offset], d_in.i[aligned_offset],
d_in.i[aligned_offset], d_in.i[aligned_offset]);
EXPECT_ASSERTION(
ozz::math::simd_int4::Load1PtrU(reinterpret_cast<const int*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::LoadXPtr(d_in.i + aligned_offset),
d_in.i[aligned_offset], 0, 0, 0);
EXPECT_ASSERTION(ozz::math::simd_int4::LoadXPtr(d_in.i + aligned_offset + 1),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::Load1Ptr(d_in.i + aligned_offset),
d_in.i[aligned_offset], d_in.i[aligned_offset],
d_in.i[aligned_offset], d_in.i[aligned_offset]);
EXPECT_ASSERTION(ozz::math::simd_int4::Load1Ptr(d_in.i + aligned_offset + 1),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::Load2Ptr(d_in.i + aligned_offset),
d_in.i[aligned_offset], d_in.i[aligned_offset + 1], 0, 0);
EXPECT_ASSERTION(ozz::math::simd_int4::Load2Ptr(d_in.i + aligned_offset + 1),
"alignment");
EXPECT_SIMDINT_EQ(
ozz::math::simd_int4::Load2PtrU(d_in.i + aligned_offset + 1),
d_in.i[aligned_offset + 1], d_in.i[aligned_offset + 2], 0, 0);
EXPECT_ASSERTION(
ozz::math::simd_int4::Load2PtrU(reinterpret_cast<const int*>(d_in.c + 1)),
"alignment");
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::Load3Ptr(d_in.i + aligned_offset),
d_in.i[aligned_offset], d_in.i[aligned_offset + 1],
d_in.i[aligned_offset + 2], 0);
EXPECT_ASSERTION(ozz::math::simd_int4::Load3Ptr(d_in.i + aligned_offset + 1),
"alignment");
EXPECT_SIMDINT_EQ(
ozz::math::simd_int4::Load3PtrU(d_in.i + aligned_offset + 1),
d_in.i[aligned_offset + 1], d_in.i[aligned_offset + 2],
d_in.i[aligned_offset + 3], 0);
EXPECT_ASSERTION(
ozz::math::simd_int4::Load3PtrU(reinterpret_cast<const int*>(d_in.c + 1)),
"alignment");
}
TEST(GetInt, ozz_simd_math) {
const SimdInt4 i = ozz::math::simd_int4::Load(1, 2, 3, 4);
EXPECT_EQ(ozz::math::GetX(i), 1);
EXPECT_EQ(ozz::math::GetY(i), 2);
EXPECT_EQ(ozz::math::GetZ(i), 3);
EXPECT_EQ(ozz::math::GetW(i), 4);
}
TEST(SetInt, ozz_simd_math) {
const SimdInt4 a = ozz::math::simd_int4::Load(1, 2, 3, 4);
const SimdInt4 b = ozz::math::simd_int4::Load(5, 6, 7, 8);
EXPECT_SIMDINT_EQ(ozz::math::SetX(a, b), 5, 2, 3, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetY(a, b), 1, 5, 3, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetZ(a, b), 1, 2, 5, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetW(a, b), 1, 2, 3, 5);
EXPECT_ASSERTION(ozz::math::SetI(a, b, 4), "Invalid index, out of range.");
EXPECT_SIMDINT_EQ(ozz::math::SetI(a, b, 0), 5, 2, 3, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetI(a, b, 1), 1, 5, 3, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetI(a, b, 2), 1, 2, 5, 4);
EXPECT_SIMDINT_EQ(ozz::math::SetI(a, b, 3), 1, 2, 3, 5);
}
TEST(StoreIntPtr, ozz_simd_math) {
const SimdInt4 i4 = ozz::math::simd_int4::Load(-1, 1, 2, 3);
union Data {
int i[4 + 4]; // The 2nd float isn't aligned to a SimdInt4.
SimdInt4 i4[2]; // Forces alignment.
char c[(4 + 4) * sizeof(int)]; // The 2nd char isn't aligned to an integer.
};
{
Data d_out = {};
ozz::math::StorePtrU(i4, d_out.i + 1);
EXPECT_EQ(d_out.i[0], 0);
EXPECT_EQ(d_out.i[1], -1);
EXPECT_EQ(d_out.i[2], 1);
EXPECT_EQ(d_out.i[3], 2);
EXPECT_EQ(d_out.i[4], 3);
EXPECT_ASSERTION(
ozz::math::StorePtrU(i4, reinterpret_cast<int*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store1PtrU(i4, d_out.i + 1);
EXPECT_EQ(d_out.i[0], 0);
EXPECT_EQ(d_out.i[1], -1);
EXPECT_EQ(d_out.i[2], 0);
EXPECT_EQ(d_out.i[3], 0);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(
ozz::math::Store1PtrU(i4, reinterpret_cast<int*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store2PtrU(i4, d_out.i + 1);
EXPECT_EQ(d_out.i[0], 0);
EXPECT_EQ(d_out.i[1], -1);
EXPECT_EQ(d_out.i[2], 1);
EXPECT_EQ(d_out.i[3], 0);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(
ozz::math::Store2Ptr(i4, reinterpret_cast<int*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::Store3PtrU(i4, d_out.i + 1);
EXPECT_EQ(d_out.i[0], 0);
EXPECT_EQ(d_out.i[1], -1);
EXPECT_EQ(d_out.i[2], 1);
EXPECT_EQ(d_out.i[3], 2);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(
ozz::math::Store3Ptr(i4, reinterpret_cast<int*>(d_out.c + 1)),
"alignment");
}
{
Data d_out = {};
ozz::math::StorePtr(i4, d_out.i);
EXPECT_EQ(d_out.i[0], -1);
EXPECT_EQ(d_out.i[1], 1);
EXPECT_EQ(d_out.i[2], 2);
EXPECT_EQ(d_out.i[3], 3);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(ozz::math::StorePtr(i4, d_out.i + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store1Ptr(i4, d_out.i);
EXPECT_EQ(d_out.i[0], -1);
EXPECT_EQ(d_out.i[1], 0);
EXPECT_EQ(d_out.i[2], 0);
EXPECT_EQ(d_out.i[3], 0);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(ozz::math::Store1Ptr(i4, d_out.i + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store2Ptr(i4, d_out.i);
EXPECT_EQ(d_out.i[0], -1);
EXPECT_EQ(d_out.i[1], 1);
EXPECT_EQ(d_out.i[2], 0);
EXPECT_EQ(d_out.i[3], 0);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(ozz::math::Store2Ptr(i4, d_out.i + 1), "alignment");
}
{
Data d_out = {};
ozz::math::Store3Ptr(i4, d_out.i);
EXPECT_EQ(d_out.i[0], -1);
EXPECT_EQ(d_out.i[1], 1);
EXPECT_EQ(d_out.i[2], 2);
EXPECT_EQ(d_out.i[3], 0);
EXPECT_EQ(d_out.i[4], 0);
EXPECT_ASSERTION(ozz::math::Store3Ptr(i4, d_out.i + 1), "alignment");
}
}
TEST(ConstantInt, ozz_simd_math) {
const SimdInt4 zero = ozz::math::simd_int4::zero();
EXPECT_SIMDINT_EQ(zero, 0, 0, 0, 0);
const SimdInt4 one = ozz::math::simd_int4::one();
EXPECT_SIMDINT_EQ(one, 1, 1, 1, 1);
const SimdInt4 x_axis = ozz::math::simd_int4::x_axis();
EXPECT_SIMDINT_EQ(x_axis, 1, 0, 0, 0);
const SimdInt4 y_axis = ozz::math::simd_int4::y_axis();
EXPECT_SIMDINT_EQ(y_axis, 0, 1, 0, 0);
const SimdInt4 z_axis = ozz::math::simd_int4::z_axis();
EXPECT_SIMDINT_EQ(z_axis, 0, 0, 1, 0);
const SimdInt4 w_axis = ozz::math::simd_int4::w_axis();
EXPECT_SIMDINT_EQ(w_axis, 0, 0, 0, 1);
const SimdInt4 all_true = ozz::math::simd_int4::all_true();
EXPECT_SIMDINT_EQ(all_true, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
const SimdInt4 all_false = ozz::math::simd_int4::all_false();
EXPECT_SIMDINT_EQ(all_false, 0, 0, 0, 0);
const SimdInt4 mask_sign = ozz::math::simd_int4::mask_sign();
EXPECT_SIMDINT_EQ(mask_sign, 0x80000000, 0x80000000, 0x80000000, 0x80000000);
const SimdInt4 mask_sign_xyz = ozz::math::simd_int4::mask_sign_xyz();
EXPECT_SIMDINT_EQ(mask_sign_xyz, 0x80000000, 0x80000000, 0x80000000,
0x00000000);
const SimdInt4 mask_sign_w = ozz::math::simd_int4::mask_sign_w();
EXPECT_SIMDINT_EQ(mask_sign_w, 0x00000000, 0x00000000, 0x00000000,
0x80000000);
const SimdInt4 mask_not_sign = ozz::math::simd_int4::mask_not_sign();
EXPECT_SIMDINT_EQ(mask_not_sign, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff);
const SimdInt4 mask_ffff = ozz::math::simd_int4::mask_ffff();
EXPECT_SIMDINT_EQ(mask_ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
const SimdInt4 mask_0000 = ozz::math::simd_int4::mask_0000();
EXPECT_SIMDINT_EQ(mask_0000, 0, 0, 0, 0);
const SimdInt4 mask_fff0 = ozz::math::simd_int4::mask_fff0();
EXPECT_SIMDINT_EQ(mask_fff0, 0xffffffff, 0xffffffff, 0xffffffff, 0);
const SimdInt4 mask_f000 = ozz::math::simd_int4::mask_f000();
EXPECT_SIMDINT_EQ(mask_f000, 0xffffffff, 0, 0, 0);
const SimdInt4 mask_0f00 = ozz::math::simd_int4::mask_0f00();
EXPECT_SIMDINT_EQ(mask_0f00, 0, 0xffffffff, 0, 0);
const SimdInt4 mask_00f0 = ozz::math::simd_int4::mask_00f0();
EXPECT_SIMDINT_EQ(mask_00f0, 0, 0, 0xffffffff, 0);
const SimdInt4 mask_000f = ozz::math::simd_int4::mask_000f();
EXPECT_SIMDINT_EQ(mask_000f, 0, 0, 0, 0xffffffff);
}
TEST(SplatInt, ozz_simd_math) {
const SimdInt4 i = ozz::math::simd_int4::Load(1, -1, 2, -3);
const SimdInt4 x = ozz::math::SplatX(i);
EXPECT_SIMDINT_EQ(x, 1, 1, 1, 1);
const SimdInt4 y = ozz::math::SplatY(i);
EXPECT_SIMDINT_EQ(y, -1, -1, -1, -1);
const SimdInt4 z = ozz::math::SplatZ(i);
EXPECT_SIMDINT_EQ(z, 2, 2, 2, 2);
const SimdInt4 w = ozz::math::SplatW(i);
EXPECT_SIMDINT_EQ(w, -3, -3, -3, -3);
const SimdInt4 s3210 = ozz::math::Swizzle<3, 2, 1, 0>(i);
EXPECT_SIMDINT_EQ(s3210, -3, 2, -1, 1);
const SimdInt4 s0123 = ozz::math::Swizzle<0, 1, 2, 3>(i);
EXPECT_SIMDINT_EQ(s0123, 1, -1, 2, -3);
const SimdInt4 s0011 = ozz::math::Swizzle<0, 0, 1, 1>(i);
EXPECT_SIMDINT_EQ(s0011, 1, 1, -1, -1);
const SimdInt4 s2233 = ozz::math::Swizzle<2, 2, 3, 3>(i);
EXPECT_SIMDINT_EQ(s2233, 2, 2, -3, -3);
const SimdInt4 s0101 = ozz::math::Swizzle<0, 1, 0, 1>(i);
EXPECT_SIMDINT_EQ(s0101, 1, -1, 1, -1);
const SimdInt4 s2323 = ozz::math::Swizzle<2, 3, 2, 3>(i);
EXPECT_SIMDINT_EQ(s2323, 2, -3, 2, -3);
}
TEST(FromFloat, ozz_simd_math) {
const ozz::math::SimdFloat4 f =
ozz::math::simd_float4::Load(0.f, 46.93f, 46.26f, -93.99f);
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::FromFloatRound(f), 0, 47, 46, -94);
EXPECT_SIMDINT_EQ(ozz::math::simd_int4::FromFloatTrunc(f), 0, 46, 46, -93);
}
TEST(ArithmeticInt, ozz_simd_math) {
const SimdInt4 a = ozz::math::simd_int4::Load(0, 1, 2, 3);
const SimdInt4 b = ozz::math::simd_int4::Load(4, 5, -6, 7);
const SimdInt4 hadd2 = ozz::math::HAdd2(a);
EXPECT_SIMDINT_EQ(hadd2, 1, 1, 2, 3);
const SimdInt4 hadd3 = ozz::math::HAdd3(a);
EXPECT_SIMDINT_EQ(hadd3, 3, 1, 2, 3);
const SimdInt4 hadd4 = ozz::math::HAdd4(a);
EXPECT_SIMDINT_EQ(hadd4, 6, 1, 2, 3);
const SimdInt4 abs = ozz::math::Abs(b);
EXPECT_SIMDINT_EQ(abs, 4, 5, 6, 7);
const SimdInt4 sign = ozz::math::Sign(b);
EXPECT_SIMDINT_EQ(sign, 0, 0, 0x80000000, 0);
}
TEST(CompareInt, ozz_simd_math) {
const SimdInt4 a = ozz::math::simd_int4::Load(0, 1, 2, 3);
const SimdInt4 b = ozz::math::simd_int4::Load(4, 1, -6, 7);
const SimdInt4 c = ozz::math::simd_int4::Load(4, 5, 6, 7);
const SimdInt4 min = ozz::math::Min(a, b);
EXPECT_SIMDINT_EQ(min, 0, 1, -6, 3);
const SimdInt4 max = ozz::math::Max(a, b);
EXPECT_SIMDINT_EQ(max, 4, 1, 2, 7);
const SimdInt4 min0 = ozz::math::Min0(b);
EXPECT_SIMDINT_EQ(min0, 0, 0, -6, 0);
const SimdInt4 max0 = ozz::math::Max0(b);
EXPECT_SIMDINT_EQ(max0, 4, 1, 0, 7);
EXPECT_SIMDINT_EQ(
ozz::math::Clamp(a, ozz::math::simd_int4::Load(-12, 2, 9, 3), c), 0, 2, 6,
3);
const SimdInt4 eq1 = ozz::math::CmpEq(a, b);
EXPECT_SIMDINT_EQ(eq1, 0, 0xffffffff, 0, 0);
const SimdInt4 eq2 = ozz::math::CmpEq(a, a);
EXPECT_SIMDINT_EQ(eq2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
const SimdInt4 neq1 = ozz::math::CmpNe(a, b);
EXPECT_SIMDINT_EQ(neq1, 0xffffffff, 0, 0xffffffff, 0xffffffff);
const SimdInt4 neq2 = ozz::math::CmpNe(a, a);
EXPECT_SIMDINT_EQ(neq2, 0, 0, 0, 0);
const SimdInt4 lt = ozz::math::CmpLt(a, b);
EXPECT_SIMDINT_EQ(lt, 0xffffffff, 0, 0, 0xffffffff);
const SimdInt4 le = ozz::math::CmpLe(a, b);
EXPECT_SIMDINT_EQ(le, 0xffffffff, 0xffffffff, 0, 0xffffffff);
const SimdInt4 gt = ozz::math::CmpGt(a, b);
EXPECT_SIMDINT_EQ(gt, 0, 0, 0xffffffff, 0);
const SimdInt4 ge = ozz::math::CmpGe(a, b);
EXPECT_SIMDINT_EQ(ge, 0, 0xffffffff, 0xffffffff, 0);
}
TEST(MaskInt, ozz_simd_math) {
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::all_false()), 0x00000000);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::all_true()), 0x0000000f);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::mask_f000()), 0x00000001);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::mask_0f00()), 0x00000002);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::mask_00f0()), 0x00000004);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::mask_000f()), 0x00000008);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::Load(
0xffffffff, 0x00000000, 0x80000001, 0x7fffffff)),
0x00000005);
EXPECT_EQ(ozz::math::MoveMask(ozz::math::simd_int4::Load(
0xffffffff, 0x1000000f, 0x80000001, 0x8ffffffe)),
0x0000000d);
EXPECT_TRUE(ozz::math::AreAllFalse(ozz::math::simd_int4::all_false()));
EXPECT_FALSE(ozz::math::AreAllFalse(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllFalse(ozz::math::simd_int4::mask_000f()));
EXPECT_TRUE(ozz::math::AreAllTrue(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllTrue(ozz::math::simd_int4::all_false()));
EXPECT_FALSE(ozz::math::AreAllTrue(ozz::math::simd_int4::mask_000f()));
EXPECT_TRUE(ozz::math::AreAllFalse3(ozz::math::simd_int4::all_false()));
EXPECT_TRUE(ozz::math::AreAllFalse3(ozz::math::simd_int4::mask_000f()));
EXPECT_FALSE(ozz::math::AreAllFalse3(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllFalse3(ozz::math::simd_int4::mask_f000()));
EXPECT_TRUE(ozz::math::AreAllTrue3(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllTrue3(ozz::math::simd_int4::all_false()));
EXPECT_FALSE(ozz::math::AreAllTrue3(ozz::math::simd_int4::mask_f000()));
EXPECT_TRUE(ozz::math::AreAllFalse2(ozz::math::simd_int4::all_false()));
EXPECT_TRUE(ozz::math::AreAllFalse2(ozz::math::simd_int4::mask_000f()));
EXPECT_FALSE(ozz::math::AreAllFalse2(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllFalse2(ozz::math::simd_int4::mask_f000()));
EXPECT_TRUE(ozz::math::AreAllTrue2(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllTrue2(ozz::math::simd_int4::all_false()));
EXPECT_FALSE(ozz::math::AreAllTrue2(ozz::math::simd_int4::mask_f000()));
EXPECT_TRUE(ozz::math::AreAllFalse1(ozz::math::simd_int4::all_false()));
EXPECT_TRUE(ozz::math::AreAllFalse1(ozz::math::simd_int4::mask_000f()));
EXPECT_FALSE(ozz::math::AreAllFalse1(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllFalse1(ozz::math::simd_int4::mask_f000()));
EXPECT_TRUE(ozz::math::AreAllTrue1(ozz::math::simd_int4::all_true()));
EXPECT_FALSE(ozz::math::AreAllTrue1(ozz::math::simd_int4::all_false()));
EXPECT_TRUE(ozz::math::AreAllTrue1(ozz::math::simd_int4::mask_f000()));
}
TEST(LogicalInt, ozz_simd_math) {
const SimdInt4 a = ozz::math::simd_int4::Load(0xffffffff, 0x00000000,
0x80000001, 0x7fffffff);
const SimdInt4 b = ozz::math::simd_int4::Load(0x80000001, 0xffffffff,
0x7fffffff, 0x00000000);
const SimdInt4 c = ozz::math::simd_int4::Load(0x01234567, 0x89abcdef,
0x01234567, 0x89abcdef);
const SimdInt4 cond = ozz::math::simd_int4::Load(0xffffffff, 0x00000000,
0xffffffff, 0x00000000);
const SimdInt4 andm = ozz::math::And(a, b);
EXPECT_SIMDINT_EQ(andm, 0x80000001, 0x00000000, 0x00000001, 0x00000000);
const SimdInt4 andnm = ozz::math::AndNot(a, b);
EXPECT_SIMDINT_EQ(andnm, 0x7ffffffe, 0x00000000, 0x80000000, 0x7fffffff);
const SimdInt4 orm = ozz::math::Or(a, b);
EXPECT_SIMDINT_EQ(orm, 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff);
const SimdInt4 xorm = ozz::math::Xor(a, b);
EXPECT_SIMDINT_EQ(xorm, 0x7ffffffe, 0xffffffff, 0xfffffffe, 0x7fffffff);
const SimdInt4 select = ozz::math::Select(cond, b, c);
EXPECT_SIMDINT_EQ(select, 0x80000001, 0x89abcdef, 0x7fffffff, 0x89abcdef);
}
TEST(ShiftInt, ozz_simd_math) {
const SimdInt4 a = ozz::math::simd_int4::Load(0xffffffff, 0x00000000,
0x80000001, 0x7fffffff);
const SimdInt4 shift_l = ozz::math::ShiftL(a, 3);
EXPECT_SIMDINT_EQ(shift_l, 0xfffffff8, 0x00000000, 0x00000008, 0xfffffff8);
const SimdInt4 shift_r = ozz::math::ShiftR(a, 3);
EXPECT_SIMDINT_EQ(shift_r, 0xffffffff, 0x00000000, 0xf0000000, 0x0fffffff);
const SimdInt4 shift_ru = ozz::math::ShiftRu(a, 3);
EXPECT_SIMDINT_EQ(shift_ru, 0x1fffffff, 0x00000000, 0x10000000, 0x0fffffff);
}
@@ -0,0 +1,72 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_math_archive.h"
#include "gtest/gtest.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/io/archive.h"
#include "ozz/base/maths/simd_math.h"
TEST(SimdMathArchive, ozz_simd_math) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write soa math types.
ozz::io::OArchive o(&stream, endianess);
const ozz::math::SimdFloat4 of4 =
ozz::math::simd_float4::Load(46.f, 58.f, 14.f, 5.f);
o << of4;
const ozz::math::SimdInt4 oi4 = ozz::math::simd_int4::Load(46, 58, 14, 5);
o << oi4;
const ozz::math::Float4x4 of44 = {
{ozz::math::simd_float4::Load(46.f, 58.f, 14.f, 5.f),
ozz::math::simd_float4::Load(26.f, 35.f, 1.f, 27.f),
ozz::math::simd_float4::Load(99.f, 11.f, 4.f, 46.f),
ozz::math::simd_float4::Load(58.f, 26.f, 14.f, 99.f)}};
o << of44;
// Reads soa math types.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
ozz::math::SimdFloat4 if4;
i >> if4;
EXPECT_SIMDFLOAT_EQ(if4, 46.f, 58.f, 14.f, 5.f);
ozz::math::SimdInt4 ii4;
i >> ii4;
EXPECT_SIMDINT_EQ(ii4, 46, 58, 14, 5);
ozz::math::Float4x4 if44;
i >> if44;
EXPECT_FLOAT4x4_EQ(if44, 46.f, 58.f, 14.f, 5.f, 26.f, 35.f, 1.f, 27.f, 99.f,
11.f, 4.f, 46.f, 58.f, 26.f, 14.f, 99.f);
}
}
@@ -0,0 +1,122 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_math.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::SimdFloat4;
TEST(TransposeFloat, ozz_simd_math) {
const SimdFloat4 src[4] = {
ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)};
SimdFloat4 t4x1[1];
ozz::math::Transpose4x1(src, t4x1);
EXPECT_SIMDFLOAT_EQ(t4x1[0], 0.f, 4.f, 8.f, 12.f);
SimdFloat4 t1x4[4];
ozz::math::Transpose1x4(src, t1x4);
EXPECT_SIMDFLOAT_EQ(t1x4[0], 0.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t1x4[1], 1.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t1x4[2], 2.f, 0.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t1x4[3], 3.f, 0.f, 0.f, 0.f);
SimdFloat4 t4x2[2];
ozz::math::Transpose4x2(src, t4x2);
EXPECT_SIMDFLOAT_EQ(t4x2[0], 0.f, 4.f, 8.f, 12.f);
EXPECT_SIMDFLOAT_EQ(t4x2[1], 1.f, 5.f, 9.f, 13.f);
SimdFloat4 t2x4[4];
ozz::math::Transpose2x4(src, t2x4);
EXPECT_SIMDFLOAT_EQ(t2x4[0], 0.f, 4.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t2x4[1], 1.f, 5.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t2x4[2], 2.f, 6.f, 0.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t2x4[3], 3.f, 7.f, 0.f, 0.f);
SimdFloat4 t4x3[3];
ozz::math::Transpose4x3(src, t4x3);
EXPECT_SIMDFLOAT_EQ(t4x3[0], 0.f, 4.f, 8.f, 12.f);
EXPECT_SIMDFLOAT_EQ(t4x3[1], 1.f, 5.f, 9.f, 13.f);
EXPECT_SIMDFLOAT_EQ(t4x3[2], 2.f, 6.f, 10.f, 14.f);
SimdFloat4 t3x4[4];
ozz::math::Transpose3x4(src, t3x4);
EXPECT_SIMDFLOAT_EQ(t3x4[0], 0.f, 4.f, 8.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t3x4[1], 1.f, 5.f, 9.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t3x4[2], 2.f, 6.f, 10.f, 0.f);
EXPECT_SIMDFLOAT_EQ(t3x4[3], 3.f, 7.f, 11.f, 0.f);
SimdFloat4 t4x4[4];
ozz::math::Transpose4x4(src, t4x4);
EXPECT_SIMDFLOAT_EQ(t4x4[0], 0.f, 4.f, 8.f, 12.f);
EXPECT_SIMDFLOAT_EQ(t4x4[1], 1.f, 5.f, 9.f, 13.f);
EXPECT_SIMDFLOAT_EQ(t4x4[2], 2.f, 6.f, 10.f, 14.f);
EXPECT_SIMDFLOAT_EQ(t4x4[3], 3.f, 7.f, 11.f, 15.f);
const SimdFloat4 src2[16] = {
ozz::math::simd_float4::Load(0.f, 16.f, 32.f, 48.f),
ozz::math::simd_float4::Load(1.f, 17.f, 33.f, 49.f),
ozz::math::simd_float4::Load(2.f, 18.f, 34.f, 50.f),
ozz::math::simd_float4::Load(3.f, 19.f, 35.f, 51.f),
ozz::math::simd_float4::Load(4.f, 20.f, 36.f, 52.f),
ozz::math::simd_float4::Load(5.f, 21.f, 37.f, 53.f),
ozz::math::simd_float4::Load(6.f, 22.f, 38.f, 54.f),
ozz::math::simd_float4::Load(7.f, 23.f, 39.f, 55.f),
ozz::math::simd_float4::Load(8.f, 24.f, 40.f, 56.f),
ozz::math::simd_float4::Load(9.f, 25.f, 41.f, 57.f),
ozz::math::simd_float4::Load(10.f, 26.f, 42.f, 58.f),
ozz::math::simd_float4::Load(11.f, 27.f, 43.f, 59.f),
ozz::math::simd_float4::Load(12.f, 28.f, 44.f, 60.f),
ozz::math::simd_float4::Load(13.f, 29.f, 45.f, 61.f),
ozz::math::simd_float4::Load(14.f, 30.f, 46.f, 62.f),
ozz::math::simd_float4::Load(15.f, 31.f, 47.f, 63.f)};
SimdFloat4 t16x16[16];
ozz::math::Transpose16x16(src2, t16x16);
EXPECT_SIMDFLOAT_EQ(t16x16[0], 0.f, 1.f, 2.f, 3.f);
EXPECT_SIMDFLOAT_EQ(t16x16[1], 4.f, 5.f, 6.f, 7.f);
EXPECT_SIMDFLOAT_EQ(t16x16[2], 8.f, 9.f, 10.f, 11.f);
EXPECT_SIMDFLOAT_EQ(t16x16[3], 12.f, 13.f, 14.f, 15.f);
EXPECT_SIMDFLOAT_EQ(t16x16[4], 16.f, 17.f, 18.f, 19.f);
EXPECT_SIMDFLOAT_EQ(t16x16[5], 20.f, 21.f, 22.f, 23.f);
EXPECT_SIMDFLOAT_EQ(t16x16[6], 24.f, 25.f, 26.f, 27.f);
EXPECT_SIMDFLOAT_EQ(t16x16[7], 28.f, 29.f, 30.f, 31.f);
EXPECT_SIMDFLOAT_EQ(t16x16[8], 32.f, 33.f, 34.f, 35.f);
EXPECT_SIMDFLOAT_EQ(t16x16[9], 36.f, 37.f, 38.f, 39.f);
EXPECT_SIMDFLOAT_EQ(t16x16[10], 40.f, 41.f, 42.f, 43.f);
EXPECT_SIMDFLOAT_EQ(t16x16[11], 44.f, 45.f, 46.f, 47.f);
EXPECT_SIMDFLOAT_EQ(t16x16[12], 48.f, 49.f, 50.f, 51.f);
EXPECT_SIMDFLOAT_EQ(t16x16[13], 52.f, 53.f, 54.f, 55.f);
EXPECT_SIMDFLOAT_EQ(t16x16[14], 56.f, 57.f, 58.f, 59.f);
EXPECT_SIMDFLOAT_EQ(t16x16[15], 60.f, 61.f, 62.f, 63.f);
}
@@ -0,0 +1,460 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/simd_quaternion.h"
#include <limits>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
using ozz::math::SimdQuaternion;
TEST(QuaternionConstant, ozz_simd_math) {
EXPECT_SIMDQUATERNION_EQ(SimdQuaternion::identity(), 0.f, 0.f, 0.f, 1.f);
}
TEST(QuaternionArithmetic, ozz_simd_math) {
const SimdQuaternion a = {
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, .70710677f)};
const SimdQuaternion b = {
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, .70710677f)};
const SimdQuaternion c = {
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, -.70710677f)};
const SimdQuaternion denorm = {
ozz::math::simd_float4::Load(1.414212f, 0.f, 0.f, 1.414212f)};
const SimdQuaternion zero = {ozz::math::simd_float4::zero()};
EXPECT_SIMDINT_EQ(IsNormalized(a), 0xffffffff, 0, 0, 0);
EXPECT_SIMDINT_EQ(IsNormalized(b), 0xffffffff, 0, 0, 0);
EXPECT_SIMDINT_EQ(IsNormalized(c), 0xffffffff, 0, 0, 0);
EXPECT_SIMDINT_EQ(IsNormalized(denorm), 0, 0, 0, 0);
const SimdQuaternion conjugate = Conjugate(a);
EXPECT_SIMDQUATERNION_EQ(conjugate, -.70710677f, 0.f, 0.f, .70710677f);
const SimdQuaternion negate = -a;
EXPECT_SIMDQUATERNION_EQ(negate, -.70710677f, 0.f, 0.f, -.70710677f);
const SimdQuaternion mul0 = a * conjugate;
EXPECT_SIMDQUATERNION_EQ(mul0, 0.f, 0.f, 0.f, 1.f);
const SimdQuaternion mul1 = conjugate * a;
EXPECT_SIMDQUATERNION_EQ(mul1, 0.f, 0.f, 0.f, 1.f);
const SimdQuaternion q1234 = {
ozz::math::simd_float4::Load(1.f, 2.f, 3.f, 4.f)};
const SimdQuaternion q5678 = {
ozz::math::simd_float4::Load(5.f, 6.f, 7.f, 8.f)};
const SimdQuaternion mul12345678 = q1234 * q5678;
EXPECT_SIMDQUATERNION_EQ(mul12345678, 24.f, 48.f, 48.f, -6.f);
EXPECT_ASSERTION(Normalize(zero), "is not normalizable");
const SimdQuaternion norm = Normalize(denorm);
EXPECT_SIMDINT_EQ(IsNormalized(norm), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ(norm, .7071068f, 0.f, 0.f, .7071068f);
// EXPECT_ASSERTION(NormalizeSafe(denorm, zero), "_safer is not normalized");
const SimdQuaternion norm_safe = NormalizeSafe(denorm, b);
EXPECT_SIMDINT_EQ(IsNormalized(norm_safe), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ(norm_safe, .7071068f, 0.f, 0.f, .7071068f);
const SimdQuaternion norm_safer = NormalizeSafe(zero, b);
EXPECT_SIMDINT_EQ(IsNormalized(norm_safer), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ(norm_safer, 0.f, .70710677f, 0.f, .70710677f);
EXPECT_ASSERTION(NormalizeEst(zero), "is not normalizable");
const SimdQuaternion norm_est = NormalizeEst(denorm);
EXPECT_SIMDINT_EQ(IsNormalizedEst(norm_est), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ_EST(norm_est, .7071068f, 0.f, 0.f, .7071068f);
// EXPECT_ASSERTION(NormalizeSafe(denorm, zero), "_safer is not normalized");
const SimdQuaternion norm_safe_est = NormalizeSafeEst(denorm, b);
EXPECT_SIMDINT_EQ(IsNormalizedEst(norm_safe_est), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ_EST(norm_safe_est, .7071068f, 0.f, 0.f, .7071068f);
const SimdQuaternion norm_safer_est = NormalizeSafeEst(zero, b);
EXPECT_SIMDINT_EQ(IsNormalizedEst(norm_safer_est), 0xffffffff, 0, 0, 0);
EXPECT_SIMDQUATERNION_EQ_EST(norm_safer_est, 0.f, .70710677f, 0.f,
.70710677f);
}
TEST(QuaternionFromVectors, ozz_simd_math) {
// Returns identity for a 0 length vector
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::zero(),
ozz::math::simd_float4::x_axis()),
0.f, 0.f, 0.f, 1.f);
// pi/2 around y
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::z_axis(),
ozz::math::simd_float4::x_axis()),
0.f, 0.707106769f, 0.f, 0.707106769f);
// Non unit pi/2 around y
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::z_axis(),
ozz::math::simd_float4::x_axis() *
ozz::math::simd_float4::Load1(27.f)),
0.f, 0.707106769f, 0.f, 0.707106769f);
// Minus pi/2 around y
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::z_axis()),
0.f, -0.707106769f, 0.f, 0.707106769f);
// pi/2 around x
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::z_axis()),
0.707106769f, 0.f, 0.f, 0.707106769f);
// pi/2 around z
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::y_axis()),
0.f, 0.f, 0.707106769f, 0.707106769f);
// pi/2 around z also
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(
ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 99.f),
ozz::math::simd_float4::Load(-0.707106769f, 0.707106769f, 0.f, 93.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Non unit pi/2 around z also
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(
ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 99.f) *
ozz::math::simd_float4::Load1(9.f),
ozz::math::simd_float4::Load(-0.707106769f, 0.707106769f, 0.f, 93.f) *
ozz::math::simd_float4::Load1(46.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Non-unit pi/2 around z
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::y_axis() *
ozz::math::simd_float4::Load1(2.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Aligned vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis()),
0.f, 0.f, 0.f, 1.f);
// Non-unit aligned vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis() *
ozz::math::simd_float4::Load1(2.f)),
0.f, 0.f, 0.f, 1.f);
// Opposed vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::x_axis(),
-ozz::math::simd_float4::x_axis()),
0.f, 1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(-ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis()),
0.f, -1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::y_axis(),
-ozz::math::simd_float4::y_axis()),
0.f, 0.f, 1.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(-ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::y_axis()),
0.f, 0.f, -1.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(ozz::math::simd_float4::z_axis(),
-ozz::math::simd_float4::z_axis()),
0.f, -1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(-ozz::math::simd_float4::z_axis(),
ozz::math::simd_float4::z_axis()),
0.f, 1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(
ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 93.f),
-ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 99.f)),
-0.707106769f, 0.707106769f, 0.f, 0.f);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(
ozz::math::simd_float4::Load(0.f, 0.707106769f, 0.707106769f, 93.f),
-ozz::math::simd_float4::Load(0.f, 0.707106769f, 0.707106769f, 99.f)),
0.f, -0.707106769f, 0.707106769f, 0.f);
// Non-unit opposed vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromVectors(
ozz::math::simd_float4::Load(2.f, 2.f, 2.f, 0.f),
ozz::math::simd_float4::Load(-2.f, -2.f, -2.f, 0.f)),
0.f, -0.707106769f, 0.707106769f, 0);
}
TEST(QuaternionFromUnitVectors, ozz_simd_math) {
// assert 0 length vectors
EXPECT_ASSERTION(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::zero(),
ozz::math::simd_float4::x_axis()),
"Input vectors must be normalized.");
EXPECT_ASSERTION(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::zero()),
"Input vectors must be normalized.");
// assert non unit vectors
EXPECT_ASSERTION(
SimdQuaternion::FromUnitVectors(
ozz::math::simd_float4::x_axis() * ozz::math::simd_float4::Load1(2.f),
ozz::math::simd_float4::x_axis()),
"Input vectors must be normalized.");
EXPECT_ASSERTION(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis() *
ozz::math::simd_float4::Load1(.5f)),
"Input vectors must be normalized.");
// pi/2 around y
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::z_axis(),
ozz::math::simd_float4::x_axis()),
0.f, 0.707106769f, 0.f, 0.707106769f);
// Minus pi/2 around y
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::z_axis()),
0.f, -0.707106769f, 0.f, 0.707106769f);
// pi/2 around x
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::z_axis()),
0.707106769f, 0.f, 0.f, 0.707106769f);
// pi/2 around z
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::y_axis()),
0.f, 0.f, 0.707106769f, 0.707106769f);
// pi/2 around z also
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(
ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 99.f),
ozz::math::simd_float4::Load(-0.707106769f, 0.707106769f, 0.f, 93.f)),
0.f, 0.f, 0.707106769f, 0.707106769f);
// Aligned vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis()),
0.f, 0.f, 0.f, 1.f);
// Opposed vectors
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::x_axis(),
-ozz::math::simd_float4::x_axis()),
0.f, 1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(-ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::x_axis()),
0.f, -1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::y_axis(),
-ozz::math::simd_float4::y_axis()),
0.f, 0.f, 1.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(-ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::y_axis()),
0.f, 0.f, -1.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(ozz::math::simd_float4::z_axis(),
-ozz::math::simd_float4::z_axis()),
0.f, -1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(-ozz::math::simd_float4::z_axis(),
ozz::math::simd_float4::z_axis()),
0.f, 1.f, 0.f, 0);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(
ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 93.f),
-ozz::math::simd_float4::Load(0.707106769f, 0.707106769f, 0.f, 99.f)),
-0.707106769f, 0.707106769f, 0.f, 0.f);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromUnitVectors(
ozz::math::simd_float4::Load(0.f, 0.707106769f, 0.707106769f, 93.f),
-ozz::math::simd_float4::Load(0.f, 0.707106769f, 0.707106769f, 99.f)),
0.f, -0.707106769f, 0.707106769f, 0.f);
}
TEST(QuaternionAxisAngle, ozz_simd_math) {
// Expect assertions from invalid inputs
EXPECT_ASSERTION(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::zero(),
ozz::math::simd_float4::zero()),
"axis is not normalized.");
#ifndef NDEBUG
const SimdQuaternion unorm = {
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 2.f)};
#endif // NDEBUG
EXPECT_ASSERTION(ToAxisAngle(unorm), "_q is not normalized.");
// Identity
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::x_axis(),
ozz::math::simd_float4::zero()),
0.f, 0.f, 0.f, 1.f);
EXPECT_SIMDFLOAT_EQ(ToAxisAngle(SimdQuaternion::identity()), 1.f, 0.f, 0.f,
0.f);
// Other axis angles
const ozz::math::SimdFloat4 pi_2 =
ozz::math::simd_float4::LoadX(ozz::math::kPi_2);
const SimdQuaternion qy_pi_2 =
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::y_axis(), pi_2);
EXPECT_SIMDQUATERNION_EQ(qy_pi_2, 0.f, .70710677f, 0.f, .70710677f);
EXPECT_SIMDFLOAT_EQ(ToAxisAngle(qy_pi_2), 0.f, 1.f, 0.f, ozz::math::kPi_2);
const SimdQuaternion qy_mpi_2 =
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::y_axis(), -pi_2);
EXPECT_SIMDQUATERNION_EQ(qy_mpi_2, 0.f, -.70710677f, 0.f, .70710677f);
EXPECT_SIMDFLOAT_EQ(ToAxisAngle(qy_mpi_2), 0.f, -1.f, 0.f,
ozz::math::kPi_2); // q = -q
const SimdQuaternion qmy_pi_2 =
SimdQuaternion::FromAxisAngle(-ozz::math::simd_float4::y_axis(), pi_2);
EXPECT_SIMDQUATERNION_EQ(qmy_pi_2, 0.f, -.70710677f, 0.f, .70710677f);
const ozz::math::SimdFloat4 any_axis =
ozz::math::simd_float4::Load(.819865f, .033034f, -.571604f, 99.f);
const ozz::math::SimdFloat4 any_angle =
ozz::math::simd_float4::Load(1.123f, 99.f, 26.f, 93.f);
const SimdQuaternion qany =
SimdQuaternion::FromAxisAngle(any_axis, any_angle);
EXPECT_SIMDQUATERNION_EQ(qany, .4365425f, .017589169f, -.30435428f,
.84645736f);
EXPECT_SIMDFLOAT_EQ(ToAxisAngle(qany), .819865f, .033034f, -.571604f, 1.123f);
}
TEST(QuaternionAxisCosAngle, ozz_simd_math) {
// Expect assertions from invalid inputs
EXPECT_ASSERTION(
SimdQuaternion::FromAxisCosAngle(ozz::math::simd_float4::zero(),
ozz::math::simd_float4::Load1(0.f)),
"axis is not normalized");
EXPECT_ASSERTION(SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load1(-1.0000001f)),
"cos is not in \\[-1,1\\] range.");
EXPECT_ASSERTION(SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load1(1.0000001f)),
"cos is not in \\[-1,1\\] range.");
// Identity
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load(1.f, 99.f, 93.f, 5.f)),
0.f, 0.f, 0.f, 1.f);
// Other axis angles
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load(std::cos(ozz::math::kPi_2), 99.f, 93.f,
5.f)),
0.f, .70710677f, 0.f, .70710677f);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisCosAngle(
-ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load(std::cos(ozz::math::kPi_2), 99.f, 93.f,
5.f)),
0.f, -.70710677f, 0.f, .70710677f);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::Load(std::cos(3.f * ozz::math::kPi_4), 99.f,
93.f, 5.f)),
0.f, 0.923879504f, 0.f, 0.382683426f);
EXPECT_SIMDQUATERNION_EQ(
SimdQuaternion::FromAxisCosAngle(
ozz::math::simd_float4::Load(.819865f, .033034f, -.571604f, 99.f),
ozz::math::simd_float4::Load(std::cos(1.123f), 99.f, 93.f, 5.f)),
.4365425f, .017589169f, -.30435428f, .84645736f);
}
TEST(QuaternionTransformVector, ozz_simd_math) {
// 0 length
EXPECT_SIMDFLOAT3_EQ(TransformVector(SimdQuaternion::FromAxisAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::zero()),
ozz::math::simd_float4::zero()),
0, 0, 0);
// Unit length
EXPECT_SIMDFLOAT3_EQ(TransformVector(SimdQuaternion::FromAxisAngle(
ozz::math::simd_float4::y_axis(),
ozz::math::simd_float4::zero()),
ozz::math::simd_float4::z_axis()),
0, 0, 1);
const ozz::math::SimdFloat4 pi_2 =
ozz::math::simd_float4::LoadX(ozz::math::kPi_2);
EXPECT_SIMDFLOAT3_EQ(
TransformVector(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::y_axis(), pi_2),
ozz::math::simd_float4::y_axis()),
0, 1, 0);
EXPECT_SIMDFLOAT3_EQ(
TransformVector(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::y_axis(), pi_2),
ozz::math::simd_float4::x_axis()),
0, 0, -1);
EXPECT_SIMDFLOAT3_EQ(
TransformVector(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::y_axis(), pi_2),
ozz::math::simd_float4::z_axis()),
1, 0, 0);
// Non unit
EXPECT_SIMDFLOAT3_EQ(
TransformVector(
SimdQuaternion::FromAxisAngle(ozz::math::simd_float4::z_axis(), pi_2),
ozz::math::simd_float4::x_axis() *
ozz::math::simd_float4::Load1(2.f)),
0, 2, 0);
}
@@ -0,0 +1,306 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/soa_float4x4.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::SoaFloat3;
using ozz::math::SoaFloat4;
using ozz::math::SoaFloat4x4;
using ozz::math::SoaQuaternion;
TEST(SoaFloat4x4Constant, ozz_soa_math) {
const SoaFloat4x4 identity = SoaFloat4x4::identity();
EXPECT_SOAFLOAT4x4_EQ(identity, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
}
TEST(SoaFloat4x4Arithmetic, ozz_soa_math) {
const SoaFloat4x4 m0 = {
{{ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(2.f, 0.f, 0.f, -1.f),
ozz::math::simd_float4::Load(3.f, 0.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(4.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(5.f, 1.f, 0.f, 1.f),
ozz::math::simd_float4::Load(6.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(7.f, 0.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(8.f, 0.f, 0.f, 1.f),
ozz::math::simd_float4::Load(9.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(10.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(11.f, 0.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(12.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(13.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(14.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(15.f, 1.f, 0.f, 1.f)}}};
const SoaFloat4x4 m1 = {
{{ozz::math::simd_float4::Load(-0.f, 0.f, 0.f, 1.f),
ozz::math::simd_float4::Load(-1.f, -1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-2.f, 2.f, -1.f, 0.f),
ozz::math::simd_float4::Load(-3.f, 3.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(-4.f, -4.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-5.f, 5.f, 1.f, 1.f),
ozz::math::simd_float4::Load(-6.f, 6.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-7.f, -7.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(-8.f, 8.f, 1.f, 0.f),
ozz::math::simd_float4::Load(-9.f, -9.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-10.f, -10.f, 0.f, 1.f),
ozz::math::simd_float4::Load(-11.f, 11.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(-12.f, -12.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-13.f, 13.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-14.f, -14.f, 0.f, 0.f),
ozz::math::simd_float4::Load(-15.f, 15.f, 1.f, 1.f)}}};
const SoaFloat4x4 m2 = {
{{ozz::math::simd_float4::Load(2.f, 0.f, 0.f, 1.f),
ozz::math::simd_float4::Load(0.f, -1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 2.f, -1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 3.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(0.f, -4.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 5.f, 1.f, 1.f),
ozz::math::simd_float4::Load(-2.f, 6.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, -7.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(0.f, 8.f, 1.f, 0.f),
ozz::math::simd_float4::Load(3.f, -9.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, -10.f, 0.f, 1.f),
ozz::math::simd_float4::Load(0.f, 11.f, 0.f, 0.f)},
{ozz::math::simd_float4::Load(0.f, -12.f, 0.f, 0.f),
ozz::math::simd_float4::Load(46.f, 13.f, 0.f, 0.f),
ozz::math::simd_float4::Load(12.f, -14.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 15.f, 1.f, 1.f)}}};
const SoaFloat4 v = {ozz::math::simd_float4::Load(0.f, 1.f, -2.f, 3.f),
ozz::math::simd_float4::Load(-1.f, 2.f, 5.f, 46.f),
ozz::math::simd_float4::Load(-2.f, 3.f, 7.f, -1.f),
ozz::math::simd_float4::Load(-3.f, 4.f, 0.f, 1.f)};
const SoaFloat4 mul_vector = m0 * v;
EXPECT_SOAFLOAT4_EQ(mul_vector, -56.f, 1.f, 0.f, -1.f, -62.f, 2.f, 0.f, 46,
-68.f, 3.f, 0.f, -3.f, -74.f, 4.f, 0.f, 1.f);
const SoaFloat4x4 mul_mat = m0 * m1;
EXPECT_SOAFLOAT4x4_EQ(
mul_mat, -56.f, 0.f, 0.f, 0.f, -62.f, -1.f, 0.f, 0.f, -68.f, 2.f, 0.f,
-1.f, -74.f, 3.f, 0.f, 0.f, -152.f, -4.f, 0.f, 0.f, -174.f, 5.f, 0.f, 1.f,
-196.f, 6.f, 0.f, 0.f, -218.f, -7.f, 0.f, 0.f, -248.f, 8.f, 0.f, 1.f,
-286.f, -9.f, 0.f, 0.f, -324.f, -10.f, 0.f, 0.f, -362.f, 11.f, 0.f, 0.f,
-344.f, -12.f, 0.f, 0.f, -398.f, 13.f, 0.f, 0.f, -452.f, -14.f, 0.f, 0.f,
-506.f, 15.f, 0.f, 1.f);
const SoaFloat4x4 add_mat = m0 + m1;
EXPECT_SOAFLOAT4x4_EQ(
add_mat, 0.f, 1.f, 0.f, 1.f, 0.f, -1.f, 0.f, 0.f, 0.f, 2.f, -1.f, -1.f,
0.f, 3.f, 0.f, 0.f, 0.f, -4.f, 0.f, 0.f, 0.f, 6.f, 1.f, 2.f, 0.f, 6.f,
0.f, 0.f, 0.f, -7.f, 0.f, 0.f, 0.f, 8.f, 1.f, 1.f, 0.f, -9.f, 0.f, 0.f,
0.f, -9.f, 0.f, 1.f, 0.f, 11.f, 0.f, 0.f, 0.f, -12.f, 0.f, 0.f, 0.f, 13.f,
0.f, 0.f, 0.f, -14.f, 0.f, 0.f, 0.f, 16.f, 1.f, 2.f);
const SoaFloat4x4 sub_mat = m0 - m1;
EXPECT_SOAFLOAT4x4_EQ(
sub_mat, 0.f, 1.f, 0.f, -1.f, 2.f, 1.f, 0.f, 0.f, 4.f, -2.f, 1.f, -1.f,
6.f, -3.f, 0.f, 0.f, 8.f, 4.f, 0.f, 0.f, 10.f, -4.f, -1.f, 0.f, 12.f,
-6.f, 0.f, 0.f, 14.f, 7.f, 0.f, 0.f, 16.f, -8.f, -1.f, 1.f, 18.f, 9.f,
0.f, 0.f, 20.f, 11.f, 0.f, -1.f, 22.f, -11.f, 0.f, 0.f, 24.f, 12.f, 0.f,
0.f, 26.f, -13.f, 0.f, 0.f, 28.f, 14.f, 0.f, 0.f, 30.f, -14.f, -1.f, 0.f);
const SoaFloat4x4 transpose = Transpose(m0);
EXPECT_SOAFLOAT4x4_EQ(
transpose, 0.f, 1.f, 0.f, 0.f, 4.f, 0.f, 0.f, 0.f, 8.f, 0.f, 0.f, 1.f,
12.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 5.f, 1.f, 0.f, 1.f, 9.f, 0.f,
0.f, 0.f, 13.f, 0.f, 0.f, 0.f, 2.f, 0.f, 0.f, -1.f, 6.f, 0.f, 0.f, 0.f,
10.f, 1.f, 0.f, 0.f, 14.f, 0.f, 0.f, 0.f, 3.f, 0.f, 0.f, 0.f, 7.f, 0.f,
0.f, 0.f, 11.f, 0.f, 0.f, 0.f, 15.f, 1.f, 0.f, 1.f);
const SoaFloat4x4 invert_ident = Invert(SoaFloat4x4::identity());
EXPECT_SOAFLOAT4x4_EQ(
invert_ident, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
const SoaFloat4x4 invert = Invert(m2);
EXPECT_SOAFLOAT4x4_EQ(invert, .5f, .216667f, 0.f, 1.f, 0.f, 2.75f, 0.f, 0.f,
0.f, 1.6f, 1.f, 0.f, 0.f, .066666f, 0.f, 0.f, 0.f, .2f,
0.f, 0.f, 0.f, 2.5f, 1.f, 1.f, .333333f, 1.4f, 0.f, 0.f,
0.f, .1f, 0.f, 0.f, 0.f, .25f, -1.f, 0.f, -.5f, .5f,
0.f, 0.f, 0.f, .25f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
.233333f, 0.f, 0.f, 6.f, .5f, 0.f, 0.f, -15.33333f, .3f,
0.f, 0.f, 1.f, .03333f, 1.f, 1.f);
const SoaFloat4x4 invert_mul = m2 * invert;
EXPECT_SOAFLOAT4x4_EQ(invert_mul, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
// EXPECT_ASSERTION(Invert(m0), "Matrix is not invertible");
// Invertible
ozz::math::SimdInt4 invertible;
EXPECT_SOAFLOAT4x4_EQ(
Invert(m2, &invertible), .5f, .216667f, 0.f, 1.f, 0.f, 2.75f, 0.f, 0.f,
0.f, 1.6f, 1.f, 0.f, 0.f, .066666f, 0.f, 0.f, 0.f, .2f, 0.f, 0.f, 0.f,
2.5f, 1.f, 1.f, .333333f, 1.4f, 0.f, 0.f, 0.f, .1f, 0.f, 0.f, 0.f, .25f,
-1.f, 0.f, -.5f, .5f, 0.f, 0.f, 0.f, .25f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f,
0.f, .233333f, 0.f, 0.f, 6.f, .5f, 0.f, 0.f, -15.33333f, .3f, 0.f, 0.f,
1.f, .03333f, 1.f, 1.f);
EXPECT_SIMDINT_EQ(invertible, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
// Non invertible
EXPECT_ASSERTION(Invert(m0), "Matrix is not invertible");
ozz::math::SimdInt4 not_invertible;
EXPECT_SOAFLOAT4x4_EQ(
Invert(m0, &not_invertible), 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 1.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 1.f);
EXPECT_SIMDINT_EQ(not_invertible, 0, 0xffffffff, 0, 0xffffffff);
}
TEST(SoaFloat4x4Scale, ozz_soa_math) {
const SoaFloat4x4 m0 = {
{{ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, -1.f, 0.f),
ozz::math::simd_float4::Load(2.f, 0.f, 2.f, -1.f),
ozz::math::simd_float4::Load(3.f, 0.f, 3.f, 0.f)},
{ozz::math::simd_float4::Load(4.f, 0.f, -4.f, 0.f),
ozz::math::simd_float4::Load(5.f, 1.f, 5.f, 1.f),
ozz::math::simd_float4::Load(6.f, 0.f, 6.f, 0.f),
ozz::math::simd_float4::Load(7.f, 0.f, -7.f, 0.f)},
{ozz::math::simd_float4::Load(8.f, 0.f, 8.f, 1.f),
ozz::math::simd_float4::Load(9.f, 0.f, -9.f, 0.f),
ozz::math::simd_float4::Load(10.f, 1.f, -10.f, 0.f),
ozz::math::simd_float4::Load(11.f, 0.f, 11.f, 0.f)},
{ozz::math::simd_float4::Load(12.f, 0.f, -12.f, 0.f),
ozz::math::simd_float4::Load(13.f, 0.f, 13.f, 0.f),
ozz::math::simd_float4::Load(14.f, 0.f, -14.f, 0.f),
ozz::math::simd_float4::Load(15.f, 1.f, 15.f, 1.f)}}};
const SoaFloat4 v = {ozz::math::simd_float4::Load(0.f, 1.f, -2.f, 3.f),
ozz::math::simd_float4::Load(-1.f, 2.f, 5.f, 46.f),
ozz::math::simd_float4::Load(-2.f, 3.f, 7.f, -1.f),
ozz::math::simd_float4::Load(-3.f, 4.f, 0.f, 1.f)};
const SoaFloat4x4 scaling = SoaFloat4x4::Scaling(v);
EXPECT_SOAFLOAT4x4_EQ(scaling, 0.f, 1.f, -2.f, 3.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-1.f, 2.f, 5.f, 46.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -2.f, 3.f,
7.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
const SoaFloat4x4 scale_mul = m0 * scaling;
EXPECT_SOAFLOAT4x4_EQ(scale_mul, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 2.f, 0.f, 0.f,
0.f, -4.f, -3.f, 0.f, 0.f, -6.f, 0.f, -4.f, 0.f, -20.f,
0.f, -5.f, 2.f, 25.f, 46.f, -6.f, 0.f, 30.f, 0.f, -7.f,
0.f, -35.f, 0.f, -16.f, 0.f, 56.f, -1.f, -18.f, 0.f,
-63.f, 0.f, -20.f, 3.f, -70.f, 0.f, -22.f, 0.f, 77.f,
0.f, 12.f, 0.f, -12.f, 0.f, 13.f, 0.f, 13.f, 0.f, 14.f,
0.f, -14.f, 0.f, 15.f, 1.f, 15.f, 1.f);
const SoaFloat4x4 scale = Scale(m0, v);
EXPECT_SOAFLOAT4x4_EQ(scale, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 2.f, 0.f, 0.f, 0.f,
-4.f, -3.f, 0.f, 0.f, -6.f, 0.f, -4.f, 0.f, -20.f, 0.f,
-5.f, 2.f, 25.f, 46.f, -6.f, 0.f, 30.f, 0.f, -7.f, 0.f,
-35.f, 0.f, -16.f, 0.f, 56.f, -1.f, -18.f, 0.f, -63.f,
0.f, -20.f, 3.f, -70.f, 0.f, -22.f, 0.f, 77.f, 0.f,
12.f, 0.f, -12.f, 0.f, 13.f, 0.f, 13.f, 0.f, 14.f, 0.f,
-14.f, 0.f, 15.f, 1.f, 15.f, 1.f);
}
TEST(SoaFloat4x4Rotate, ozz_soa_math) {
#ifndef NDEBUG
const SoaQuaternion unormalized =
SoaQuaternion::Load(ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 1.f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 1.f, 1.f, 1.f));
#endif // NDEBUG
EXPECT_ASSERTION(SoaFloat4x4::FromQuaternion(unormalized), "IsNormalized");
const SoaFloat4x4 identity =
SoaFloat4x4::FromQuaternion(SoaQuaternion::identity());
EXPECT_SOAFLOAT4x4_EQ(identity, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
const SoaQuaternion quaternion = SoaQuaternion::Load(
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, -.382683432f),
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, 0.f),
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, .70710677f, 1.f, .9238795f));
const SoaFloat4x4 matrix = SoaFloat4x4::FromQuaternion(quaternion);
EXPECT_SOAFLOAT4x4_EQ(
matrix, 0.f, 0.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, -1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 1.f, 1.f, .707106f, 0.f, 0.f,
0.f, -.707106f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
.707106f, 0.f, 0.f, 1.f, .707106f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
}
TEST(SoaFloat4x4Affine, ozz_soa_math) {
const SoaFloat4x4 identity = SoaFloat4x4::FromAffine(
SoaFloat3::zero(), SoaQuaternion::identity(), SoaFloat3::one());
EXPECT_SOAFLOAT4x4_EQ(identity, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
const SoaFloat3 translation =
SoaFloat3::Load(ozz::math::simd_float4::Load(0.f, 46.f, 7.f, -12.f),
ozz::math::simd_float4::Load(0.f, 12.f, 7.f, -46.f),
ozz::math::simd_float4::Load(0.f, 0.f, 7.f, 46.f));
const SoaFloat3 scale =
SoaFloat3::Load(ozz::math::simd_float4::Load(1.f, 1.f, -1.f, 0.1f),
ozz::math::simd_float4::Load(1.f, 2.f, -1.f, 0.1f),
ozz::math::simd_float4::Load(1.f, 3.f, -1.f, 0.1f));
const SoaQuaternion quaternion = SoaQuaternion::Load(
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, -.382683432f),
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, 0.f),
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(0.f, .70710677f, 1.f, .9238795f));
const SoaFloat4x4 matrix =
SoaFloat4x4::FromAffine(translation, quaternion, scale);
EXPECT_SOAFLOAT4x4_EQ(
matrix, 0.f, 0.f, -1.f, .1f, 0.f, 0.f, 0.f, 0.f, 1.f, -1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 2.f, -1.f, .0707106f, 0.f, 0.f,
0.f, -.0707106f, 0.f, 0.f, 0.f, 0.f, 1.f, 3.f, 0.f, 0.f, 0.f, 0.f, 0.f,
.0707106f, 0.f, 0.f, -1.f, .0707106f, 0.f, 0.f, 0.f, 0.f, 0.f, 46.f, 7.f,
-12.f, 0.f, 12.f, 7.f, -46.f, 0.f, 0.f, 7.f, 46.f, 1.f, 1.f, 1.f, 1.f);
}
@@ -0,0 +1,515 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/soa_float.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::SimdFloat4;
using ozz::math::SoaFloat2;
using ozz::math::SoaFloat3;
using ozz::math::SoaFloat4;
TEST(SoaFloatLoad4, ozz_soa_math) {
EXPECT_SOAFLOAT4_EQ(
SoaFloat4::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f,
14.f, 15.f);
EXPECT_SOAFLOAT4_EQ(
SoaFloat4::Load(
SoaFloat3::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f)),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f,
14.f, 15.f);
EXPECT_SOAFLOAT4_EQ(
SoaFloat4::Load(
SoaFloat2::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f)),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f,
14.f, 15.f);
}
TEST(SoaFloatLoad3, ozz_soa_math) {
EXPECT_SOAFLOAT3_EQ(
SoaFloat3::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f);
EXPECT_SOAFLOAT3_EQ(
SoaFloat3::Load(
SoaFloat2::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f)),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f);
}
TEST(SoaFloatLoad2, ozz_soa_math) {
EXPECT_SOAFLOAT2_EQ(
SoaFloat2::Load(ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f)),
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
}
TEST(SoaFloatConstant4, ozz_soa_math) {
EXPECT_SOAFLOAT4_EQ(SoaFloat4::zero(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT4_EQ(SoaFloat4::one(), 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f);
EXPECT_SOAFLOAT4_EQ(SoaFloat4::x_axis(), 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT4_EQ(SoaFloat4::y_axis(), 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f,
1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT4_EQ(SoaFloat4::z_axis(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT4_EQ(SoaFloat4::w_axis(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
}
TEST(SoaFloatConstant3, ozz_soa_math) {
EXPECT_SOAFLOAT3_EQ(SoaFloat3::zero(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT3_EQ(SoaFloat3::one(), 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f);
EXPECT_SOAFLOAT3_EQ(SoaFloat3::x_axis(), 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT3_EQ(SoaFloat3::y_axis(), 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f,
1.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAFLOAT3_EQ(SoaFloat3::z_axis(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 1.f, 1.f, 1.f, 1.f);
}
TEST(SoaFloatConstant2, ozz_soa_math) {
EXPECT_SOAFLOAT2_EQ(SoaFloat2::zero(), 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f);
EXPECT_SOAFLOAT2_EQ(SoaFloat2::one(), 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f);
EXPECT_SOAFLOAT2_EQ(SoaFloat2::x_axis(), 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f,
0.f);
EXPECT_SOAFLOAT2_EQ(SoaFloat2::y_axis(), 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f,
1.f);
}
TEST(SoaFloatArithmetic4, ozz_soa_math) {
const SoaFloat4 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f)};
const SoaFloat4 b = {
ozz::math::simd_float4::Load(-.5f, -1.f, -2.f, -3.f),
ozz::math::simd_float4::Load(-4.f, -5.f, -6.f, -7.f),
ozz::math::simd_float4::Load(-8.f, -9.f, -10.f, -11.f),
ozz::math::simd_float4::Load(-12.f, -13.f, -14.f, -15.f)};
const SoaFloat4 c = {ozz::math::simd_float4::Load(.05f, .1f, .2f, .3f),
ozz::math::simd_float4::Load(.4f, .5f, .6f, .7f),
ozz::math::simd_float4::Load(.8f, .9f, 1.f, 1.1f),
ozz::math::simd_float4::Load(1.2f, 1.3f, 1.4f, 1.5f)};
const SoaFloat4 add = a + b;
EXPECT_SOAFLOAT4_EQ(add, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
const SoaFloat4 sub = a - b;
EXPECT_SOAFLOAT4_EQ(sub, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f, 16.f,
18.f, 20.f, 22.f, 24.f, 26.f, 28.f, 30.f);
const SoaFloat4 neg = -a;
EXPECT_SOAFLOAT4_EQ(neg, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f,
-9.f, -10.f, -11.f, -12.f, -13.f, -14.f, -15.f);
const SoaFloat4 mul = a * b;
EXPECT_SOAFLOAT4_EQ(mul, -0.25f, -1.f, -4.f, -9.f, -16.f, -25.f, -36.f, -49.f,
-64.f, -81.f, -100.f, -121.f, -144.f, -169.f, -196.f,
-225.f);
const SoaFloat4 mul_add = MAdd(a, b, c);
EXPECT_SOAFLOAT4_EQ(mul_add, -0.2f, -.9f, -3.8f, -8.7f, -15.6f, -24.5f,
-35.4f, -48.3f, -63.2f, -80.1f, -99.f, -119.9f, -142.8f,
-167.7f, -194.6f, -223.5f);
const SoaFloat4 mul_scal = a * ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT4_EQ(mul_scal, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f, 16.f,
18.f, 20.f, 22.f, 24.f, 26.f, 28.f, 30.f);
const SoaFloat4 div = a / b;
EXPECT_SOAFLOAT4_EQ(div, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f,
-1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f);
const SoaFloat4 div_scal = a / ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT4_EQ(div_scal, 0.25f, .5f, 1.f, 1.5f, 2.f, 2.5f, 3.f, 3.5f,
4.f, 4.5, 5.f, 5.5f, 6.f, 6.5f, 7.f, 7.5f);
const SimdFloat4 hadd4 = HAdd(a);
EXPECT_SOAFLOAT1_EQ(hadd4, 24.5f, 28.f, 32.f, 36.f);
const SimdFloat4 dot = Dot(a, b);
EXPECT_SOAFLOAT1_EQ(dot, -224.25f, -276.f, -336.f, -404.f);
const SimdFloat4 length = Length(a);
EXPECT_SOAFLOAT1_EQ(length, 14.974979f, 16.613247f, 18.3303f, 20.09975f);
const SimdFloat4 length2 = LengthSqr(a);
EXPECT_SOAFLOAT1_EQ(length2, 224.25f, 276.f, 336.f, 404.f);
EXPECT_ASSERTION(Normalize(SoaFloat4::zero()), "_v is not normalizable");
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalized(a)));
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalizedEst(a)));
const SoaFloat4 normalize = Normalize(a);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize)));
EXPECT_SOAFLOAT4_EQ(normalize, .033389f, .0601929f, .1091089f, .1492555f,
.267112f, .300964f, .3273268f, .348263f, .53422445f,
.541736f, .545544f, .547270f, .80133667f, .782508f,
.763762f, .74627789f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const SoaFloat4 safe = ozz::math::SoaFloat4::x_axis();
const SoaFloat4 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safe)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safe)));
EXPECT_SOAFLOAT4_EQ(normalize_safe, .033389f, .0601929f, .1091089f, .1492555f,
.267112f, .300964f, .3273268f, .348263f, .53422445f,
.541736f, .545544f, .547270f, .80133667f, .782508f,
.763762f, .74627789f);
const SoaFloat4 normalize_safer = NormalizeSafe(SoaFloat4::zero(), safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safer)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safer)));
EXPECT_SOAFLOAT4_EQ(normalize_safer, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
const SoaFloat4 lerp_0 = Lerp(a, b, ozz::math::simd_float4::zero());
EXPECT_SOAFLOAT4_EQ(lerp_0, .5f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f,
10.f, 11.f, 12.f, 13.f, 14.f, 15.f);
const SoaFloat4 lerp_1 = Lerp(a, b, ozz::math::simd_float4::one());
EXPECT_SOAFLOAT4_EQ(lerp_1, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f,
-8.f, -9.f, -10.f, -11.f, -12.f, -13.f, -14.f, -15.f);
const SoaFloat4 lerp_0_5 = Lerp(a, b, ozz::math::simd_float4::Load1(.5f));
EXPECT_SOAFLOAT4_EQ(lerp_0_5, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
}
TEST(SoaFloatArithmetic3, ozz_soa_math) {
const SoaFloat3 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f)};
const SoaFloat3 b = {ozz::math::simd_float4::Load(-.5f, -1.f, -2.f, -3.f),
ozz::math::simd_float4::Load(-4.f, -5.f, -6.f, -7.f),
ozz::math::simd_float4::Load(-8.f, -9.f, -10.f, -11.f)};
const SoaFloat3 c = {ozz::math::simd_float4::Load(.05f, .1f, .2f, .3f),
ozz::math::simd_float4::Load(.4f, .5f, .6f, .7f),
ozz::math::simd_float4::Load(.8f, .9f, 1.f, 1.1f)};
const SoaFloat3 add = a + b;
EXPECT_SOAFLOAT3_EQ(add, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f);
const SoaFloat3 sub = a - b;
EXPECT_SOAFLOAT3_EQ(sub, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f, 16.f,
18.f, 20.f, 22.f);
const SoaFloat3 neg = -a;
EXPECT_SOAFLOAT3_EQ(neg, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f,
-9.f, -10.f, -11.f);
const SoaFloat3 mul = a * b;
EXPECT_SOAFLOAT3_EQ(mul, -0.25f, -1.f, -4.f, -9.f, -16.f, -25.f, -36.f, -49.f,
-64.f, -81.f, -100.f, -121.f);
const SoaFloat3 mul_add = MAdd(a, b, c);
EXPECT_SOAFLOAT3_EQ(mul_add, -0.2f, -.9f, -3.8f, -8.7f, -15.6f, -24.5f,
-35.4f, -48.3f, -63.2f, -80.1f, -99.f, -119.9f);
const SoaFloat3 mul_scal = a * ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT3_EQ(mul_scal, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f, 16.f,
18.f, 20.f, 22.f);
const SoaFloat3 div = a / b;
EXPECT_SOAFLOAT3_EQ(div, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f,
-1.f, -1.f, -1.f);
const SoaFloat3 div_scal = a / ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT3_EQ(div_scal, 0.25f, .5f, 1.f, 1.5f, 2.f, 2.5f, 3.f, 3.5f,
4.f, 4.5, 5.f, 5.5f);
const SimdFloat4 hadd4 = HAdd(a);
EXPECT_SOAFLOAT1_EQ(hadd4, 12.5f, 15.f, 18.f, 21.f);
const SimdFloat4 dot = Dot(a, b);
EXPECT_SOAFLOAT1_EQ(dot, -80.25f, -107.f, -140.f, -179.f);
const SimdFloat4 length = Length(a);
EXPECT_SOAFLOAT1_EQ(length, 8.958236f, 10.34408f, 11.83216f, 13.37909f);
const SimdFloat4 length2 = LengthSqr(a);
EXPECT_SOAFLOAT1_EQ(length2, 80.25f, 107.f, 140.f, 179.f);
const SoaFloat3 cross = Cross(a, b);
EXPECT_SOAFLOAT3_EQ(cross, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f);
EXPECT_ASSERTION(Normalize(SoaFloat3::zero()), "_v is not normalizable");
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalized(a)));
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalizedEst(a)));
const SoaFloat3 normalize = Normalize(a);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize)));
EXPECT_SOAFLOAT3_EQ(normalize, .055814f, .096673f, .16903f, .22423f, .446516f,
.483368f, .50709f, .52320f, .893033f, .870063f, .84515f,
.822178f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const SoaFloat3 safe = ozz::math::SoaFloat3::x_axis();
const SoaFloat3 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safe)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safe)));
EXPECT_SOAFLOAT3_EQ(normalize_safe, .055814f, .096673f, .16903f, .22423f,
.446516f, .483368f, .50709f, .52320f, .893033f, .870063f,
.84515f, .822178f);
const SoaFloat3 normalize_safer = NormalizeSafe(SoaFloat3::zero(), safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safer)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safer)));
EXPECT_SOAFLOAT3_EQ(normalize_safer, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f);
const SoaFloat3 lerp_0 = Lerp(a, b, ozz::math::simd_float4::zero());
EXPECT_SOAFLOAT3_EQ(lerp_0, .5f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f,
10.f, 11.f);
const SoaFloat3 lerp_1 = Lerp(a, b, ozz::math::simd_float4::one());
EXPECT_SOAFLOAT3_EQ(lerp_1, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f,
-8.f, -9.f, -10.f, -11.f);
const SoaFloat3 lerp_0_5 = Lerp(a, b, ozz::math::simd_float4::Load1(.5f));
EXPECT_SOAFLOAT3_EQ(lerp_0_5, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f);
}
TEST(SoaFloatArithmetic2, ozz_soa_math) {
const SoaFloat2 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f)};
const SoaFloat2 b = {ozz::math::simd_float4::Load(-.5f, -1.f, -2.f, -3.f),
ozz::math::simd_float4::Load(-4.f, -5.f, -6.f, -7.f)};
const SoaFloat2 c = {ozz::math::simd_float4::Load(.05f, .1f, .2f, .3f),
ozz::math::simd_float4::Load(.4f, .5f, .6f, .7f)};
const SoaFloat2 add = a + b;
EXPECT_SOAFLOAT2_EQ(add, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
const SoaFloat2 sub = a - b;
EXPECT_SOAFLOAT2_EQ(sub, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f);
const SoaFloat2 neg = -a;
EXPECT_SOAFLOAT2_EQ(neg, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f);
const SoaFloat2 mul = a * b;
EXPECT_SOAFLOAT2_EQ(mul, -0.25f, -1.f, -4.f, -9.f, -16.f, -25.f, -36.f,
-49.f);
const SoaFloat2 mul_add = MAdd(a, b, c);
EXPECT_SOAFLOAT2_EQ(mul_add, -0.2f, -.9f, -3.8f, -8.7f, -15.6f, -24.5f,
-35.4f, -48.3f);
const SoaFloat2 mul_scal = a * ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT2_EQ(mul_scal, 1.f, 2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 14.f);
const SoaFloat2 div = a / b;
EXPECT_SOAFLOAT2_EQ(div, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f);
const SoaFloat2 div_scal = a / ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAFLOAT2_EQ(div_scal, 0.25f, .5f, 1.f, 1.5f, 2.f, 2.5f, 3.f, 3.5f);
const SimdFloat4 hadd4 = HAdd(a);
EXPECT_SOAFLOAT1_EQ(hadd4, 4.5f, 6.f, 8.f, 10.f);
const SimdFloat4 dot = Dot(a, b);
EXPECT_SOAFLOAT1_EQ(dot, -16.25f, -26.f, -40.f, -58.f);
const SimdFloat4 length = Length(a);
EXPECT_SOAFLOAT1_EQ(length, 4.031129f, 5.09902f, 6.324555f, 7.615773f);
const SimdFloat4 length2 = LengthSqr(a);
EXPECT_SOAFLOAT1_EQ(length2, 16.25f, 26.f, 40.f, 58.f);
EXPECT_ASSERTION(Normalize(SoaFloat2::zero()), "_v is not normalizable");
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalized(a)));
EXPECT_TRUE(ozz::math::AreAllFalse(IsNormalizedEst(a)));
const SoaFloat2 normalize = Normalize(a);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize)));
EXPECT_SOAFLOAT2_EQ(normalize, .124034f, .196116f, .316227f, .393919f,
.992277f, .980580f, .9486832f, .919145f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const SoaFloat2 safe = ozz::math::SoaFloat2::x_axis();
const SoaFloat2 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safe)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safe)));
EXPECT_SOAFLOAT2_EQ(normalize, .124034f, .196116f, .316227f, .393919f,
.992277f, .980580f, .9486832f, .919145f);
const SoaFloat2 normalize_safer = NormalizeSafe(SoaFloat2::zero(), safe);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize_safer)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_safer)));
EXPECT_SOAFLOAT2_EQ(normalize_safer, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f, 0.f);
const SoaFloat2 lerp_0 = Lerp(a, b, ozz::math::simd_float4::zero());
EXPECT_SOAFLOAT2_EQ(lerp_0, .5f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
const SoaFloat2 lerp_1 = Lerp(a, b, ozz::math::simd_float4::one());
EXPECT_SOAFLOAT2_EQ(lerp_1, -.5f, -1.f, -2.f, -3.f, -4.f, -5.f, -6.f, -7.f);
const SoaFloat2 lerp_0_5 = Lerp(a, b, ozz::math::simd_float4::Load1(.5f));
EXPECT_SOAFLOAT2_EQ(lerp_0_5, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
}
TEST(SoaFloatComparison4, ozz_soa_math) {
const SoaFloat4 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(1.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(2.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(3.f, 13.f, 14.f, 15.f)};
const SoaFloat4 b = {ozz::math::simd_float4::Load(4.f, 3.f, 7.f, 3.f),
ozz::math::simd_float4::Load(2.f, -5.f, 6.f, 5.f),
ozz::math::simd_float4::Load(-6.f, 9.f, -10.f, 2.f),
ozz::math::simd_float4::Load(7.f, -8.f, 1.f, 5.f)};
const SoaFloat4 c = {ozz::math::simd_float4::Load(7.5f, 12.f, 46.f, 31.f),
ozz::math::simd_float4::Load(1.f, 58.f, 16.f, 78.f),
ozz::math::simd_float4::Load(2.5f, 9.f, 111.f, 22.f),
ozz::math::simd_float4::Load(8.f, 23.f, 41.f, 18.f)};
const SoaFloat4 min = Min(a, b);
EXPECT_SOAFLOAT4_EQ(min, .5f, 1.f, 2.f, 3.f, 1.f, -5.f, 6.f, 5.f, -6.f, 9.f,
-10.f, 2.f, 3.f, -8.f, 1.f, 5.f);
const SoaFloat4 max = Max(a, b);
EXPECT_SOAFLOAT4_EQ(max, 4.f, 3.f, 7.f, 3.f, 2.f, 5.f, 6.f, 7.f, 2.f, 9.f,
10.f, 11.f, 7.f, 13.f, 14.f, 15.f);
EXPECT_SOAFLOAT4_EQ(
Clamp(a, SoaFloat4::Load(
ozz::math::simd_float4::Load(1.5f, 5.f, -2.f, 24.f),
ozz::math::simd_float4::Load(2.f, -5.f, 7.f, 1.f),
ozz::math::simd_float4::Load(-3.f, 1.f, 200.f, 0.f),
ozz::math::simd_float4::Load(-9.f, 15.f, 46.f, -1.f)),
c),
1.5f, 5.f, 2.f, 24.f, 1.f, 5.f, 7.f, 7.f, 2.f, 9.f, 111.f, 11.f, 3.f,
15.f, 41.f, 15.f);
EXPECT_SIMDINT_EQ(a < c, 0, 0, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c > a, 0, 0, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == c, 0, 0, 0, 0);
EXPECT_SIMDINT_EQ(a != b, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
}
TEST(SoaFloatComparison3, ozz_soa_math) {
const SoaFloat3 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(1.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(2.f, 9.f, 10.f, 11.f)};
const SoaFloat3 b = {ozz::math::simd_float4::Load(4.f, 3.f, 7.f, 3.f),
ozz::math::simd_float4::Load(2.f, -5.f, 6.f, 5.f),
ozz::math::simd_float4::Load(-6.f, 9.f, -10.f, 2.f)};
const SoaFloat3 c = {ozz::math::simd_float4::Load(7.5f, 12.f, 46.f, 31.f),
ozz::math::simd_float4::Load(1.f, 58.f, 16.f, 78.f),
ozz::math::simd_float4::Load(2.5f, 9.f, 111.f, 22.f)};
const SoaFloat3 min = Min(a, b);
EXPECT_SOAFLOAT3_EQ(min, .5f, 1.f, 2.f, 3.f, 1.f, -5.f, 6.f, 5.f, -6.f, 9.f,
-10.f, 2.f);
const SoaFloat3 max = Max(a, b);
EXPECT_SOAFLOAT3_EQ(max, 4.f, 3.f, 7.f, 3.f, 2.f, 5.f, 6.f, 7.f, 2.f, 9.f,
10.f, 11.f);
EXPECT_SOAFLOAT3_EQ(
Clamp(a, SoaFloat3::Load(
ozz::math::simd_float4::Load(1.5f, 5.f, -2.f, 24.f),
ozz::math::simd_float4::Load(2.f, -5.f, 7.f, 1.f),
ozz::math::simd_float4::Load(-3.f, 1.f, 200.f, 0.f)),
c),
1.5f, 5.f, 2.f, 24.f, 1.f, 5.f, 7.f, 7.f, 2.f, 9.f, 111.f, 11.f);
EXPECT_SIMDINT_EQ(a < c, 0, 0, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c > a, 0, 0, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == c, 0, 0, 0, 0);
EXPECT_SIMDINT_EQ(a != b, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
}
TEST(SoaFloatComparison2, ozz_soa_math) {
const SoaFloat2 a = {ozz::math::simd_float4::Load(.5f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(1.f, 5.f, 6.f, 7.f)};
const SoaFloat2 b = {ozz::math::simd_float4::Load(4.f, 3.f, 7.f, 3.f),
ozz::math::simd_float4::Load(2.f, -5.f, 6.f, 5.f)};
const SoaFloat2 c = {ozz::math::simd_float4::Load(7.5f, 12.f, 46.f, 31.f),
ozz::math::simd_float4::Load(1.f, 58.f, 16.f, 78.f)};
const SoaFloat2 min = Min(a, b);
EXPECT_SOAFLOAT2_EQ(min, .5f, 1.f, 2.f, 3.f, 1.f, -5.f, 6.f, 5.f);
const SoaFloat2 max = Max(a, b);
EXPECT_SOAFLOAT2_EQ(max, 4.f, 3.f, 7.f, 3.f, 2.f, 5.f, 6.f, 7.f);
EXPECT_SOAFLOAT2_EQ(
Clamp(a,
SoaFloat2::Load(ozz::math::simd_float4::Load(1.5f, 5.f, -2.f, 24.f),
ozz::math::simd_float4::Load(2.f, -5.f, 7.f, 1.f)),
c),
1.5f, 5.f, 2.f, 24.f, 1.f, 5.f, 7.f, 7.f);
EXPECT_SIMDINT_EQ(a < c, 0, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c <= c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c > a, 0, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(c >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a >= a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
EXPECT_SIMDINT_EQ(a == c, 0, 0, 0, 0);
EXPECT_SIMDINT_EQ(a != b, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
}
@@ -0,0 +1,126 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/soa_math_archive.h"
#include "gtest/gtest.h"
#include "ozz/base/maths/gtest_math_helper.h"
#include "ozz/base/io/archive.h"
#include "ozz/base/maths/soa_float.h"
#include "ozz/base/maths/soa_float4x4.h"
#include "ozz/base/maths/soa_quaternion.h"
#include "ozz/base/maths/soa_transform.h"
TEST(SoaMathArchive, ozz_soa_math) {
for (int e = 0; e < 2; ++e) {
ozz::Endianness endianess = e == 0 ? ozz::kBigEndian : ozz::kLittleEndian;
ozz::io::MemoryStream stream;
ASSERT_TRUE(stream.opened());
// Write soa math types.
ozz::io::OArchive o(&stream, endianess);
const ozz::math::SoaFloat2 of2 = ozz::math::SoaFloat2::Load(
ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f));
o << of2;
const ozz::math::SoaFloat3 of3 = ozz::math::SoaFloat3::Load(
ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f));
o << of3;
const ozz::math::SoaFloat4 of4 = ozz::math::SoaFloat4::Load(
ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f));
o << of4;
const ozz::math::SoaQuaternion oquat = ozz::math::SoaQuaternion::Load(
ozz::math::simd_float4::Load(0.f, 1.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 5.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 9.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 13.f, 14.f, 15.f));
o << oquat;
const ozz::math::SoaTransform otrans = {of3, oquat, of3};
o << otrans;
const ozz::math::SoaFloat4x4 of44 = {
{{ozz::math::simd_float4::Load(0.f, 1.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, 0.f, -1.f, 0.f),
ozz::math::simd_float4::Load(2.f, 0.f, 2.f, -1.f),
ozz::math::simd_float4::Load(3.f, 0.f, 3.f, 0.f)},
{ozz::math::simd_float4::Load(4.f, 0.f, -4.f, 0.f),
ozz::math::simd_float4::Load(5.f, 1.f, 5.f, 1.f),
ozz::math::simd_float4::Load(6.f, 0.f, 6.f, 0.f),
ozz::math::simd_float4::Load(7.f, 0.f, -7.f, 0.f)},
{ozz::math::simd_float4::Load(8.f, 0.f, 8.f, 1.f),
ozz::math::simd_float4::Load(9.f, 0.f, -9.f, 0.f),
ozz::math::simd_float4::Load(10.f, 1.f, -10.f, 0.f),
ozz::math::simd_float4::Load(11.f, 0.f, 11.f, 0.f)},
{ozz::math::simd_float4::Load(12.f, 0.f, -12.f, 0.f),
ozz::math::simd_float4::Load(13.f, 0.f, 13.f, 0.f),
ozz::math::simd_float4::Load(14.f, 0.f, -14.f, 0.f),
ozz::math::simd_float4::Load(15.f, 1.f, 15.f, 1.f)}}};
o << of44;
// Reads soa math types.
stream.Seek(0, ozz::io::Stream::kSet);
ozz::io::IArchive i(&stream);
ozz::math::SoaFloat2 if2;
i >> if2;
EXPECT_SOAFLOAT2_EQ(if2, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
ozz::math::SoaFloat3 if3;
i >> if3;
EXPECT_SOAFLOAT3_EQ(if3, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f,
10.f, 11.f);
ozz::math::SoaFloat4 if4;
i >> if4;
EXPECT_SOAFLOAT4_EQ(if4, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f,
10.f, 11.f, 12.f, 13.f, 14.f, 15.f);
ozz::math::SoaQuaternion iquat;
i >> iquat;
EXPECT_SOAQUATERNION_EQ(iquat, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f,
9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f);
ozz::math::SoaTransform itrans;
i >> itrans;
EXPECT_SOAFLOAT3_EQ(itrans.translation, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f,
7.f, 8.f, 9.f, 10.f, 11.f);
EXPECT_SOAQUATERNION_EQ(itrans.rotation, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f,
7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f);
EXPECT_SOAFLOAT3_EQ(itrans.scale, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f,
8.f, 9.f, 10.f, 11.f);
ozz::math::SoaFloat4x4 if44;
i >> if44;
EXPECT_SOAFLOAT4x4_EQ(
if44, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, -1.f, 0.f, 2.f, 0.f, 2.f, -1.f, 3.f,
0.f, 3.f, 0.f, 4.f, 0.f, -4.f, 0.f, 5.f, 1.f, 5.f, 1.f, 6.f, 0.f, 6.f,
0.f, 7.f, 0.f, -7.f, 0.f, 8.f, 0.f, 8.f, 1.f, 9.f, 0.f, -9.f, 0.f, 10.f,
1.f, -10.f, 0.f, 11.f, 0.f, 11.f, 0.f, 12.f, 0.f, -12.f, 0.f, 13.f, 0.f,
13.f, 0.f, 14.f, 0.f, -14.f, 0.f, 15.f, 1.f, 15.f, 1.f);
}
}
@@ -0,0 +1,169 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/soa_quaternion.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::SoaQuaternion;
using ozz::math::SoaFloat4;
using ozz::math::SoaFloat3;
TEST(SoaQuaternionConstant, ozz_soa_math) {
EXPECT_SOAQUATERNION_EQ(SoaQuaternion::identity(), 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f,
1.f);
}
TEST(SoaQuaternionArithmetic, ozz_soa_math) {
const SoaQuaternion a = SoaQuaternion::Load(
ozz::math::simd_float4::Load(.70710677f, 0.f, 0.f, .382683432f),
ozz::math::simd_float4::Load(0.f, 0.f, .70710677f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(.70710677f, 1.f, .70710677f, .9238795f));
const SoaQuaternion b = SoaQuaternion::Load(
ozz::math::simd_float4::Load(0.f, .70710677f, 0.f, -.382683432f),
ozz::math::simd_float4::Load(0.f, 0.f, .70710677f, 0.f),
ozz::math::simd_float4::Load(0.f, 0.f, 0.f, 0.f),
ozz::math::simd_float4::Load(1.f, .70710677f, .70710677f, .9238795f));
const SoaQuaternion denorm =
SoaQuaternion::Load(ozz::math::simd_float4::Load(.5f, 0.f, 2.f, 3.f),
ozz::math::simd_float4::Load(4.f, 0.f, 6.f, 7.f),
ozz::math::simd_float4::Load(8.f, 0.f, 10.f, 11.f),
ozz::math::simd_float4::Load(12.f, 1.f, 14.f, 15.f));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(a)));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(b)));
EXPECT_SIMDINT_EQ(ozz::math::IsNormalized(denorm), 0, 0xffffffff, 0, 0);
const SoaQuaternion conjugate = Conjugate(a);
EXPECT_SOAQUATERNION_EQ(conjugate, -.70710677f, -0.f, -0.f, -.382683432f,
-0.f, -0.f, -.70710677f, -0.f, -0.f, -0.f, -0.f, -0.f,
.70710677f, 1.f, .70710677f, .9238795f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(conjugate)));
const SoaQuaternion negate = -a;
EXPECT_SOAQUATERNION_EQ(negate, -.70710677f, 0.f, 0.f, -.382683432f, 0.f, 0.f,
-.70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, -.70710677f,
-1.f, -.70710677f, -.9238795f);
const SoaQuaternion add = a + b;
EXPECT_SOAQUATERNION_EQ(add, .70710677f, .70710677f, 0.f, 0.f, 0.f, 0.f,
1.41421354f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.70710677f,
1.70710677f, 1.41421354f, 1.847759f);
const SoaQuaternion muls = a * ozz::math::simd_float4::Load1(2.f);
EXPECT_SOAQUATERNION_EQ(muls, 1.41421354f, 0.f, 0.f, .765366864f, 0.f, 0.f,
1.41421354f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.41421354f,
2.f, 1.41421354f, 1.847759f);
const SoaQuaternion mul0 = a * conjugate;
EXPECT_SOAQUATERNION_EQ(mul0, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(mul0)));
const SoaQuaternion mul1 = conjugate * a;
EXPECT_SOAQUATERNION_EQ(mul1, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(mul1)));
const ozz::math::SimdFloat4 dot = Dot(a, b);
EXPECT_SOAFLOAT1_EQ(dot, .70710677f, .70710677f, 1.f, .70710677f);
const SoaQuaternion normalize = Normalize(denorm);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(normalize)));
EXPECT_SOAQUATERNION_EQ(normalize, .033389f, 0.f, .1091089f, .1492555f,
.267112f, 0.f, .3273268f, .348263f, .53422445f, 0.f,
.545544f, .547270f, .80133667f, 1.f, .763762f,
.74627789f);
const SoaQuaternion normalize_est = NormalizeEst(denorm);
EXPECT_SOAQUATERNION_EQ_EST(normalize_est, .033389f, 0.f, .1091089f,
.1492555f, .267112f, 0.f, .3273268f, .348263f,
.53422445f, 0.f, .545544f, .547270f, .80133667f,
1.f, .763762f, .74627789f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(normalize_est)));
const SoaQuaternion lerp_0 = Lerp(a, b, ozz::math::simd_float4::zero());
EXPECT_SOAQUATERNION_EQ(lerp_0, .70710677f, 0.f, 0.f, .382683432f, 0.f, 0.f,
.70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, .70710677f, 1.f,
.70710677f, .9238795f);
const SoaQuaternion lerp_1 = Lerp(a, b, ozz::math::simd_float4::one());
EXPECT_SOAQUATERNION_EQ(lerp_1, 0.f, .70710677f, 0.f, -.382683432f, 0.f, 0.f,
.70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, .70710677f,
.70710677f, .9238795f);
const SoaQuaternion lerp_0_2 = Lerp(a, b, ozz::math::simd_float4::Load1(.2f));
EXPECT_SOAQUATERNION_EQ(lerp_0_2, .565685416f, .14142136f, 0.f, .22961006f,
0.f, 0.f, .70710677f, 0.f, 0.f, 0.f, 0.f, 0.f,
.76568544f, .94142133f, .70710677f, .92387950f);
const SoaQuaternion lerp_m =
Lerp(a, b, ozz::math::simd_float4::Load(0.f, 1.f, 1.f, .2f));
EXPECT_SOAQUATERNION_EQ(lerp_m, .70710677f, .70710677f, 0.f, .22961006f, 0.f,
0.f, .70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, .70710677f,
.70710677f, .70710677f, .92387950f);
const SoaQuaternion nlerp_0 = NLerp(a, b, ozz::math::simd_float4::zero());
EXPECT_SOAQUATERNION_EQ(nlerp_0, .70710677f, 0.f, 0.f, .382683432f, 0.f, 0.f,
.70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, .70710677f, 1.f,
.70710677f, .9238795f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(nlerp_0)));
const SoaQuaternion nlerp_1 = NLerp(a, b, ozz::math::simd_float4::one());
EXPECT_SOAQUATERNION_EQ(nlerp_1, 0.f, .70710677f, 0.f, -.382683432f, 0.f, 0.f,
.70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, .70710677f,
.70710677f, .9238795f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(nlerp_1)));
const SoaQuaternion nlerp_0_2 =
NLerp(a, b, ozz::math::simd_float4::Load1(.2f));
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(nlerp_0_2)));
EXPECT_SOAQUATERNION_EQ(nlerp_0_2, .59421712f, .14855431f, 0.f, .24119100f,
0.f, 0.f, .70710683f, 0.f, 0.f, 0.f, 0.f, 0.f,
.80430466f, .98890430f, .70710683f, .97047764f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(nlerp_0_2)));
const SoaQuaternion nlerp_m =
NLerp(a, b, ozz::math::simd_float4::Load(0.f, 1.f, 1.f, .2f));
EXPECT_SOAQUATERNION_EQ(nlerp_m, .70710677f, .70710677f, 0.f, .24119100f, 0.f,
0.f, .70710677f, 0.f, 0.f, 0.f, 0.f, 0.f, .70710677f,
.70710677f, .70710677f, .97047764f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalized(nlerp_m)));
const SoaQuaternion nlerp_est_m =
NLerpEst(a, b, ozz::math::simd_float4::Load(0.f, 1.f, 1.f, .2f));
EXPECT_SOAQUATERNION_EQ_EST(nlerp_est_m, .70710677f, .70710677f, 0.f,
.24119100f, 0.f, 0.f, .70710677f, 0.f, 0.f, 0.f,
0.f, 0.f, .70710677f, .70710677f, .70710677f,
.97047764f);
EXPECT_TRUE(ozz::math::AreAllTrue(IsNormalizedEst(nlerp_est_m)));
}
@@ -0,0 +1,45 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/soa_transform.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::SoaTransform;
TEST(SoaTransformConstant, ozz_soa_math) {
EXPECT_SOAFLOAT3_EQ(SoaTransform::identity().translation, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
EXPECT_SOAQUATERNION_EQ(SoaTransform::identity().rotation, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 1.f,
1.f);
EXPECT_SOAFLOAT3_EQ(SoaTransform::identity().scale, 1.f, 1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f);
}
@@ -0,0 +1,41 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/transform.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::Transform;
TEST(TransformConstant, ozz_math) {
EXPECT_FLOAT3_EQ(Transform::identity().translation, 0.f, 0.f, 0.f);
EXPECT_QUATERNION_EQ(Transform::identity().rotation, 0.f, 0.f, 0.f, 1.f);
EXPECT_FLOAT3_EQ(Transform::identity().scale, 1.f, 1.f, 1.f);
}
@@ -0,0 +1,377 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/maths/vec_float.h"
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/maths/gtest_math_helper.h"
using ozz::math::Float2;
using ozz::math::Float3;
using ozz::math::Float4;
TEST(VectorLoad4, ozz_math) {
EXPECT_FLOAT4_EQ(Float4(46.f), 46.f, 46.f, 46.f, 46.f);
EXPECT_FLOAT4_EQ(Float4(-1.f, 0.f, 1.f, 2.f), -1.f, 0.f, 1.f, 2.f);
const Float3 f3(-1.f, 0.f, 1.f);
EXPECT_FLOAT4_EQ(Float4(f3, 2.f), -1.f, 0.f, 1.f, 2.f);
const Float2 f2(-1.f, 0.f);
EXPECT_FLOAT4_EQ(Float4(f2, 1.f, 2.f), -1.f, 0.f, 1.f, 2.f);
}
TEST(VectorLoad3, ozz_math) {
EXPECT_FLOAT3_EQ(Float3(46.f), 46.f, 46.f, 46.f);
EXPECT_FLOAT3_EQ(Float3(-1.f, 0.f, 1.f), -1.f, 0.f, 1.f);
const Float2 f2(-1.f, 0.f);
EXPECT_FLOAT3_EQ(Float3(f2, 1.f), -1.f, 0.f, 1.f);
}
TEST(VectorLoad2, ozz_math) {
EXPECT_FLOAT2_EQ(Float2(46.f), 46.f, 46.f);
EXPECT_FLOAT2_EQ(Float2(-1.f, 0.f), -1.f, 0.f);
}
TEST(VectorConstant4, ozz_math) {
EXPECT_FLOAT4_EQ(Float4::zero(), 0.f, 0.f, 0.f, 0.f);
EXPECT_FLOAT4_EQ(Float4::one(), 1.f, 1.f, 1.f, 1.f);
EXPECT_FLOAT4_EQ(Float4::x_axis(), 1.f, 0.f, 0.f, 0.f);
EXPECT_FLOAT4_EQ(Float4::y_axis(), 0.f, 1.f, 0.f, 0.f);
EXPECT_FLOAT4_EQ(Float4::z_axis(), 0.f, 0.f, 1.f, 0.f);
EXPECT_FLOAT4_EQ(Float4::w_axis(), 0.f, 0.f, 0.f, 1.f);
}
TEST(VectorConstant3, ozz_math) {
EXPECT_FLOAT3_EQ(Float3::zero(), 0.f, 0.f, 0.f);
EXPECT_FLOAT3_EQ(Float3::one(), 1.f, 1.f, 1.f);
EXPECT_FLOAT3_EQ(Float3::x_axis(), 1.f, 0.f, 0.f);
EXPECT_FLOAT3_EQ(Float3::y_axis(), 0.f, 1.f, 0.f);
EXPECT_FLOAT3_EQ(Float3::z_axis(), 0.f, 0.f, 1.f);
}
TEST(VectorConstant2, ozz_math) {
EXPECT_FLOAT2_EQ(Float2::zero(), 0.f, 0.f);
EXPECT_FLOAT2_EQ(Float2::one(), 1.f, 1.f);
EXPECT_FLOAT2_EQ(Float2::x_axis(), 1.f, 0.f);
EXPECT_FLOAT2_EQ(Float2::y_axis(), 0.f, 1.f);
}
TEST(VectorArithmetic4, ozz_math) {
const Float4 a(.5f, 1.f, 2.f, 3.f);
const Float4 b(4.f, 5.f, -6.f, 7.f);
const Float4 add = a + b;
EXPECT_FLOAT4_EQ(add, 4.5f, 6.f, -4.f, 10.f);
const Float4 sub = a - b;
EXPECT_FLOAT4_EQ(sub, -3.5f, -4.f, 8.f, -4.f);
const Float4 neg = -b;
EXPECT_FLOAT4_EQ(neg, -4.f, -5.f, 6.f, -7.f);
const Float4 mul = a * b;
EXPECT_FLOAT4_EQ(mul, 2.f, 5.f, -12.f, 21.f);
const Float4 mul_scal = a * 2.f;
EXPECT_FLOAT4_EQ(mul_scal, 1.f, 2.f, 4.f, 6.f);
const Float4 div = a / b;
EXPECT_FLOAT4_EQ(div, .5f / 4.f, 1.f / 5.f, -2.f / 6.f, 3.f / 7.f);
const Float4 div_scal = a / 2.f;
EXPECT_FLOAT4_EQ(div_scal, .5f / 2.f, 1.f / 2.f, 2.f / 2.f, 3.f / 2.f);
const float hadd4 = HAdd(a);
EXPECT_FLOAT_EQ(hadd4, 6.5f);
const float dot = Dot(a, b);
EXPECT_FLOAT_EQ(dot, 16.f);
const float length = Length(a);
EXPECT_FLOAT_EQ(length, std::sqrt(14.25f));
const float length2 = LengthSqr(a);
EXPECT_FLOAT_EQ(length2, 14.25f);
EXPECT_ASSERTION(Normalize(Float4::zero()), "is not normalizable");
EXPECT_FALSE(IsNormalized(a));
const Float4 normalize = Normalize(a);
EXPECT_TRUE(IsNormalized(normalize));
EXPECT_FLOAT4_EQ(normalize, .13245323f, .26490647f, .52981293f, .79471946f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const Float4 safe(1.f, 0.f, 0.f, 0.f);
const Float4 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(IsNormalized(normalize_safe));
EXPECT_FLOAT4_EQ(normalize_safe, .13245323f, .26490647f, .52981293f,
.79471946f);
const Float4 normalize_safer = NormalizeSafe(Float4::zero(), safe);
EXPECT_TRUE(IsNormalized(normalize_safer));
EXPECT_FLOAT4_EQ(normalize_safer, safe.x, safe.y, safe.z, safe.w);
const Float4 lerp_0 = Lerp(a, b, 0.f);
EXPECT_FLOAT4_EQ(lerp_0, a.x, a.y, a.z, a.w);
const Float4 lerp_1 = Lerp(a, b, 1.f);
EXPECT_FLOAT4_EQ(lerp_1, b.x, b.y, b.z, b.w);
const Float4 lerp_0_5 = Lerp(a, b, .5f);
EXPECT_FLOAT4_EQ(lerp_0_5, (a.x + b.x) * .5f, (a.y + b.y) * .5f,
(a.z + b.z) * .5f, (a.w + b.w) * .5f);
const Float4 lerp_2 = Lerp(a, b, 2.f);
EXPECT_FLOAT4_EQ(lerp_2, 2.f * b.x - a.x, 2.f * b.y - a.y, 2.f * b.z - a.z,
2.f * b.w - a.w);
}
TEST(VectorArithmetic3, ozz_math) {
const Float3 a(.5f, 1.f, 2.f);
const Float3 b(4.f, 5.f, -6.f);
const Float3 add = a + b;
EXPECT_FLOAT3_EQ(add, 4.5f, 6.f, -4.f);
const Float3 sub = a - b;
EXPECT_FLOAT3_EQ(sub, -3.5f, -4.f, 8.f);
const Float3 neg = -b;
EXPECT_FLOAT3_EQ(neg, -4.f, -5.f, 6.f);
const Float3 mul = a * b;
EXPECT_FLOAT3_EQ(mul, 2.f, 5.f, -12.f);
const Float3 mul_scal = a * 2.f;
EXPECT_FLOAT3_EQ(mul_scal, 1.f, 2.f, 4.f);
const Float3 div = a / b;
EXPECT_FLOAT3_EQ(div, .5f / 4.f, 1.f / 5.f, -2.f / 6.f);
const Float3 div_scal = a / 2.f;
EXPECT_FLOAT3_EQ(div_scal, .5f / 2.f, 1.f / 2.f, 2.f / 2.f);
const float hadd4 = HAdd(a);
EXPECT_FLOAT_EQ(hadd4, 3.5f);
const float dot = Dot(a, b);
EXPECT_FLOAT_EQ(dot, -5.f);
const Float3 cross = Cross(a, b);
EXPECT_FLOAT3_EQ(cross, -16.f, 11.f, -1.5f);
const float length = Length(a);
EXPECT_FLOAT_EQ(length, std::sqrt(5.25f));
const float length2 = LengthSqr(a);
EXPECT_FLOAT_EQ(length2, 5.25f);
EXPECT_ASSERTION(Normalize(Float3::zero()), "is not normalizable");
EXPECT_FALSE(IsNormalized(a));
const Float3 normalize = Normalize(a);
EXPECT_TRUE(IsNormalized(normalize));
EXPECT_FLOAT3_EQ(normalize, .21821788f, .43643576f, .87287152f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const Float3 safe(1.f, 0.f, 0.f);
const Float3 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(IsNormalized(normalize_safe));
EXPECT_FLOAT3_EQ(normalize_safe, .21821788f, .43643576f, .87287152f);
const Float3 normalize_safer = NormalizeSafe(Float3::zero(), safe);
EXPECT_TRUE(IsNormalized(normalize_safer));
EXPECT_FLOAT3_EQ(normalize_safer, safe.x, safe.y, safe.z);
const Float3 lerp_0 = Lerp(a, b, 0.f);
EXPECT_FLOAT3_EQ(lerp_0, a.x, a.y, a.z);
const Float3 lerp_1 = Lerp(a, b, 1.f);
EXPECT_FLOAT3_EQ(lerp_1, b.x, b.y, b.z);
const Float3 lerp_0_5 = Lerp(a, b, .5f);
EXPECT_FLOAT3_EQ(lerp_0_5, (a.x + b.x) * .5f, (a.y + b.y) * .5f,
(a.z + b.z) * .5f);
const Float3 lerp_2 = Lerp(a, b, 2.f);
EXPECT_FLOAT3_EQ(lerp_2, 2.f * b.x - a.x, 2.f * b.y - a.y, 2.f * b.z - a.z);
}
TEST(VectorArithmetic2, ozz_math) {
const Float2 a(.5f, 1.f);
const Float2 b(4.f, 5.f);
const Float2 add = a + b;
EXPECT_FLOAT2_EQ(add, 4.5f, 6.f);
const Float2 sub = a - b;
EXPECT_FLOAT2_EQ(sub, -3.5f, -4.f);
const Float2 neg = -b;
EXPECT_FLOAT2_EQ(neg, -4.f, -5.f);
const Float2 mul = a * b;
EXPECT_FLOAT2_EQ(mul, 2.f, 5.f);
const Float2 mul_scal = a * 2.f;
EXPECT_FLOAT2_EQ(mul_scal, 1.f, 2.f);
const Float2 div = a / b;
EXPECT_FLOAT2_EQ(div, .5f / 4.f, 1.f / 5.f);
const Float2 div_scal = a / 2.f;
EXPECT_FLOAT2_EQ(div_scal, .5f / 2.f, 1.f / 2.f);
const float hadd4 = HAdd(a);
EXPECT_FLOAT_EQ(hadd4, 1.5f);
const float dot = Dot(a, b);
EXPECT_FLOAT_EQ(dot, 7.f);
const float length = Length(a);
EXPECT_FLOAT_EQ(length, std::sqrt(1.25f));
const float length2 = LengthSqr(a);
EXPECT_FLOAT_EQ(length2, 1.25f);
EXPECT_ASSERTION(Normalize(Float2::zero()), "is not normalizable");
EXPECT_FALSE(IsNormalized(a));
const Float2 normalize = Normalize(a);
EXPECT_TRUE(IsNormalized(normalize));
EXPECT_FLOAT2_EQ(normalize, .44721359f, .89442718f);
EXPECT_ASSERTION(NormalizeSafe(a, a), "_safer is not normalized");
const Float2 safe(1.f, 0.f);
const Float2 normalize_safe = NormalizeSafe(a, safe);
EXPECT_TRUE(IsNormalized(normalize_safe));
EXPECT_FLOAT2_EQ(normalize_safe, .44721359f, .89442718f);
const Float2 normalize_safer = NormalizeSafe(Float2::zero(), safe);
EXPECT_TRUE(IsNormalized(normalize_safer));
EXPECT_FLOAT2_EQ(normalize_safer, safe.x, safe.y);
const Float2 lerp_0 = Lerp(a, b, 0.f);
EXPECT_FLOAT2_EQ(lerp_0, a.x, a.y);
const Float2 lerp_1 = Lerp(a, b, 1.f);
EXPECT_FLOAT2_EQ(lerp_1, b.x, b.y);
const Float2 lerp_0_5 = Lerp(a, b, .5f);
EXPECT_FLOAT2_EQ(lerp_0_5, (a.x + b.x) * .5f, (a.y + b.y) * .5f);
const Float2 lerp_2 = Lerp(a, b, 2.f);
EXPECT_FLOAT2_EQ(lerp_2, 2.f * b.x - a.x, 2.f * b.y - a.y);
}
TEST(VectorComparison4, ozz_math) {
const Float4 a(.5f, 1.f, 2.f, 3.f);
const Float4 b(4.f, 5.f, -6.f, 7.f);
const Float4 c(4.f, 5.f, 6.f, 7.f);
const Float4 d(4.f, 5.f, 6.f, 7.1f);
const Float4 min = Min(a, b);
EXPECT_FLOAT4_EQ(min, .5f, 1.f, -6.f, 3.f);
const Float4 max = Max(a, b);
EXPECT_FLOAT4_EQ(max, 4.f, 5.f, 2.f, 7.f);
EXPECT_FLOAT4_EQ(Clamp(a, Float4(-12.f, 2.f, 9.f, 3.f), c), .5f, 2.f, 6.f,
3.f);
EXPECT_TRUE(a < c);
EXPECT_TRUE(a <= c);
EXPECT_TRUE(c <= c);
EXPECT_TRUE(c > a);
EXPECT_TRUE(c >= a);
EXPECT_TRUE(a >= a);
EXPECT_TRUE(a == a);
EXPECT_TRUE(a != b);
EXPECT_TRUE(Compare(a, a, 0.f));
EXPECT_TRUE(Compare(c, d, .2f));
EXPECT_FALSE(Compare(c, d, .05f));
}
TEST(VectorComparison3, ozz_math) {
const Float3 a(.5f, -1.f, 2.f);
const Float3 b(4.f, 5.f, -6.f);
const Float3 c(4.f, 5.f, 6.f);
const Float3 d(4.f, 5.f, 6.1f);
const Float3 min = Min(a, b);
EXPECT_FLOAT3_EQ(min, .5f, -1.f, -6.f);
const Float3 max = Max(a, b);
EXPECT_FLOAT3_EQ(max, 4.f, 5.f, 2.f);
EXPECT_FLOAT3_EQ(Clamp(a, Float3(-12.f, 2.f, 9.f), c), .5f, 2.f, 6.f);
EXPECT_TRUE(a < c);
EXPECT_TRUE(a <= c);
EXPECT_TRUE(c <= c);
EXPECT_TRUE(c > a);
EXPECT_TRUE(c >= a);
EXPECT_TRUE(a >= a);
EXPECT_TRUE(a == a);
EXPECT_TRUE(a != b);
EXPECT_TRUE(Compare(a, a, 1e-3f));
EXPECT_TRUE(Compare(c, d, .2f));
EXPECT_FALSE(Compare(c, d, .05f));
}
TEST(VectorComparison2, ozz_math) {
const Float2 a(.5f, 1.f);
const Float2 b(4.f, -5.f);
const Float2 c(4.f, 5.f);
const Float2 d(4.f, 5.1f);
const Float2 min = Min(a, b);
EXPECT_FLOAT2_EQ(min, .5f, -5.f);
const Float2 max = Max(a, b);
EXPECT_FLOAT2_EQ(max, 4.f, 1.f);
EXPECT_FLOAT2_EQ(Clamp(a, Float2(-12.f, 2.f), c), .5f, 2.f);
EXPECT_TRUE(a < c);
EXPECT_TRUE(a <= c);
EXPECT_TRUE(c <= c);
EXPECT_TRUE(c > a);
EXPECT_TRUE(c >= a);
EXPECT_TRUE(a >= a);
EXPECT_TRUE(a == a);
EXPECT_TRUE(a != b);
EXPECT_TRUE(Compare(a, a, 1e-3f));
EXPECT_TRUE(Compare(c, d, .2f));
EXPECT_FALSE(Compare(c, d, .05f));
}
+15
View File
@@ -0,0 +1,15 @@
add_executable(test_memory
allocator_tests.cc)
target_link_libraries(test_memory
ozz_base
gtest)
add_test(NAME test_memory COMMAND test_memory)
set_target_properties(test_memory PROPERTIES FOLDER "ozz/tests/base")
add_executable(test_unique_ptr
unique_ptr_tests.cc)
target_link_libraries(test_unique_ptr
ozz_base
gtest)
add_test(NAME test_unique_ptr COMMAND test_unique_ptr)
set_target_properties(test_unique_ptr PROPERTIES FOLDER "ozz/tests/base")
@@ -0,0 +1,154 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "gtest/gtest.h"
#include "ozz/base/maths/math_ex.h"
#include "ozz/base/memory/allocator.h"
TEST(Allocate, Memory) {
void* p = ozz::memory::default_allocator()->Allocate(12, 1024);
EXPECT_TRUE(p != nullptr);
EXPECT_TRUE(ozz::IsAligned(p, 1024));
// Fills allocated memory.
memset(p, 0, 12);
ozz::memory::default_allocator()->Deallocate(p);
}
TEST(MallocCompliance, Memory) {
{ // Allocating 0 byte gives a valid pointer.
void* p = ozz::memory::default_allocator()->Allocate(0, 1024);
EXPECT_TRUE(p != nullptr);
ozz::memory::default_allocator()->Deallocate(p);
}
{ // Freeing of a nullptr pointer is valid.
ozz::memory::default_allocator()->Deallocate(nullptr);
}
}
struct AlignedInts {
AlignedInts() {
for (int i = 0; i < array_size; ++i) {
array[i] = i;
}
}
AlignedInts(int _i0) {
array[0] = _i0;
for (int i = 1; i < array_size; ++i) {
array[i] = i;
}
}
AlignedInts(int _i0, int _i1) {
array[0] = _i0;
array[1] = _i1;
for (int i = 2; i < array_size; ++i) {
array[i] = i;
}
}
AlignedInts(int _i0, int _i1, int _i2) {
array[0] = _i0;
array[1] = _i1;
array[2] = _i2;
for (int i = 3; i < array_size; ++i) {
array[i] = i;
}
}
static const int array_size = 517;
alignas(64) int array[array_size];
};
TEST(NewDelete, Memory) {
AlignedInts* ai0 = ozz::New<AlignedInts>();
ASSERT_TRUE(ai0 != nullptr);
for (int i = 0; i < ai0->array_size; ++i) {
EXPECT_EQ(ai0->array[i], i);
}
ozz::Delete(ai0);
AlignedInts* ai1 = ozz::New<AlignedInts>(46);
ASSERT_TRUE(ai1 != nullptr);
EXPECT_EQ(ai1->array[0], 46);
for (int i = 1; i < ai1->array_size; ++i) {
EXPECT_EQ(ai1->array[i], i);
}
ozz::Delete(ai1);
AlignedInts* ai2 = ozz::New<AlignedInts>(46, 69);
ASSERT_TRUE(ai2 != nullptr);
EXPECT_EQ(ai2->array[0], 46);
EXPECT_EQ(ai2->array[1], 69);
for (int i = 2; i < ai2->array_size; ++i) {
EXPECT_EQ(ai2->array[i], i);
}
ozz::Delete(ai2);
AlignedInts* ai3 = ozz::New<AlignedInts>(46, 69, 58);
ASSERT_TRUE(ai3 != nullptr);
EXPECT_EQ(ai3->array[0], 46);
EXPECT_EQ(ai3->array[1], 69);
EXPECT_EQ(ai3->array[2], 58);
for (int i = 3; i < ai3->array_size; ++i) {
EXPECT_EQ(ai3->array[i], i);
}
ozz::Delete(ai3);
}
class TestAllocator : public ozz::memory::Allocator {
public:
TestAllocator() : hard_coded_address_(&hard_coded_address_) {}
void* hard_coded_address() const { return hard_coded_address_; }
private:
virtual void* Allocate(size_t _size, size_t _alignment) {
(void)_size;
(void)_alignment;
return hard_coded_address_;
}
virtual void Deallocate(void* _block) { (void)_block; }
void* hard_coded_address_;
};
TEST(AllocatorOverride, Memory) {
TestAllocator test_allocator;
ozz::memory::Allocator* previous =
ozz::memory::SetDefaulAllocator(&test_allocator);
ozz::memory::Allocator* current = ozz::memory::default_allocator();
void* alloc = current->Allocate(1, 1);
EXPECT_EQ(alloc, test_allocator.hard_coded_address());
current->Deallocate(alloc);
EXPECT_EQ(ozz::memory::SetDefaulAllocator(previous), current);
}
@@ -0,0 +1,146 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/base/memory/unique_ptr.h"
#include "ozz/base/gtest_helper.h"
TEST(Construction, unique_ptr) {
{ const ozz::unique_ptr<int> pi; }
{ const ozz::unique_ptr<int> pi(ozz::New<int>()); }
}
TEST(Reset, unique_ptr) {
{
ozz::unique_ptr<int> pi;
pi.reset(nullptr);
pi.reset(ozz::New<int>());
}
{
ozz::unique_ptr<int> pi(ozz::New<int>());
pi.reset(ozz::New<int>());
pi.reset(nullptr);
}
}
struct A {
int i;
};
TEST(Dereference, unique_ptr) {
{
const ozz::unique_ptr<int> pi;
EXPECT_TRUE(pi.get() == nullptr);
EXPECT_FALSE(pi);
}
{
const ozz::unique_ptr<int> pi(ozz::New<int>(46));
EXPECT_EQ(*pi, 46);
EXPECT_TRUE(pi.get() != nullptr);
EXPECT_TRUE(pi);
}
{
const ozz::unique_ptr<A> pa(ozz::New<A>());
pa->i = 46;
EXPECT_EQ((*pa).i, 46);
}
}
TEST(Bool, unique_ptr) {
{
const ozz::unique_ptr<int> pi;
EXPECT_TRUE(!pi);
EXPECT_FALSE(pi);
}
{
const ozz::unique_ptr<int> pi(ozz::New<int>(46));
EXPECT_FALSE(!pi);
EXPECT_TRUE(pi);
}
}
TEST(Swap, unique_ptr) {
{
int* i = ozz::New<int>(46);
ozz::unique_ptr<int> pi;
ozz::unique_ptr<int> pii(i);
EXPECT_TRUE(pi.get() == nullptr);
EXPECT_TRUE(pii.get() == i);
pi.swap(pii);
EXPECT_TRUE(pii.get() == nullptr);
EXPECT_TRUE(pi.get() == i);
}
{
int* i = ozz::New<int>(46);
ozz::unique_ptr<int> pi;
ozz::unique_ptr<int> pii(i);
EXPECT_TRUE(pi.get() == nullptr);
EXPECT_TRUE(pii.get() == i);
swap(pi, pii);
EXPECT_TRUE(pii.get() == nullptr);
EXPECT_TRUE(pi.get() == i);
}
}
TEST(Release, unique_ptr) {
int* i = ozz::New<int>(46);
{
ozz::unique_ptr<int> pi(i);
int* ri = pi.release();
EXPECT_EQ(i, ri);
}
ozz::Delete(i);
}
struct B : public A {};
TEST(Upcast, unique_ptr) {
ozz::unique_ptr<A> a = ozz::unique_ptr<B>();
a = ozz::unique_ptr<B>();
}
TEST(make_unique, unique_ptr) {
{ // No argument
EXPECT_TRUE(ozz::make_unique<int>());
EXPECT_EQ(*ozz::make_unique<int>(), 0);
}
{ // 1 argument
EXPECT_TRUE(ozz::make_unique<int>(46));
EXPECT_EQ(*ozz::make_unique<int>(46), 46);
}
{ // N arguments
auto p5 =
ozz::make_unique<std::tuple<int, int, int, int, int>>(0, 1, 2, 3, 4);
EXPECT_TRUE(p5);
EXPECT_EQ(*p5, std::make_tuple(0, 1, 2, 3, 4));
}
}
+180
View File
@@ -0,0 +1,180 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include <stdint.h>
#include <cassert>
#include <climits>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/platform.h"
TEST(StaticAssertion, Platform) {
static_assert(2 == 2, "Must compile.");
// static_assert(1 == 2, "Must not compile.);
}
namespace {
// Declares a structure that should have at least 8 bytes aligned.
struct Misc {
double d;
char c;
int i;
};
// Declares an aligned structure in order to test OZZ_ALIGN and AlignOf.
struct Aligned {
alignas(128) char c;
};
} // namespace
TEST(Alignment, Platform) {
static_assert(alignof(char) == 1, "Unexpected type size");
static_assert(alignof(double) == 8, "Unexpected type size");
static_assert(alignof(Misc) == 8, "Unexpected type size");
static_assert(alignof(Aligned) == 128, "Unexpected type size");
Aligned alined;
EXPECT_EQ(reinterpret_cast<uintptr_t>(&alined) & (128 - 1), 0u);
}
TEST(IntegerAlignment, Platform) {
{
short s = 0x1234;
int aligned_s = ozz::Align(s, 128);
EXPECT_TRUE(aligned_s == 0x1280);
EXPECT_TRUE(ozz::IsAligned(aligned_s, 128));
}
{
int i = 0x00a01234;
int aligned_i = ozz::Align(i, 1024);
EXPECT_TRUE(aligned_i == 0x00a01400);
EXPECT_TRUE(ozz::IsAligned(aligned_i, 1024));
}
}
TEST(PointerAlignment, Platform) {
void* p = reinterpret_cast<void*>(0x00a01234);
void* aligned_p = ozz::Align(p, 1024);
EXPECT_TRUE(aligned_p == reinterpret_cast<void*>(0x00a01400));
EXPECT_TRUE(ozz::IsAligned(aligned_p, 1024));
}
TEST(TypeSize, Platform) {
// Checks sizes.
static_assert(CHAR_BIT == 8, "Unexpected type size");
static_assert(sizeof(int8_t) == 1, "Unexpected type size");
static_assert(sizeof(uint8_t) == 1, "Unexpected type size");
static_assert(sizeof(int16_t) == 2, "Unexpected type size");
static_assert(sizeof(uint16_t) == 2, "Unexpected type size");
static_assert(sizeof(int32_t) == 4, "Unexpected type size");
static_assert(sizeof(uint32_t) == 4, "Unexpected type size");
static_assert(sizeof(int64_t) == 8, "Unexpected type size");
static_assert(sizeof(uint64_t) == 8, "Unexpected type size");
static_assert(sizeof(intptr_t) == sizeof(int*), "Unexpected type size");
static_assert(sizeof(uintptr_t) == sizeof(unsigned int*),
"Unexpected type size");
// Checks signs. Right shift maintains sign bit for signed types, and fills
// with 0 for unsigned types.
static_assert((int8_t(-1) >> 1) == -1, "Unexpected type sign");
static_assert((int16_t(-1) >> 1) == -1, "Unexpected type sign");
static_assert((int32_t(-1) >> 1) == -1, "Unexpected type sign");
static_assert((int64_t(-1) >> 1) == -1, "Unexpected type sign");
static_assert((uint8_t(-1) >> 1) == 0x7f, "Unexpected type sign");
static_assert((uint16_t(-1) >> 1) == 0x7fff, "Unexpected type sign");
static_assert((uint32_t(-1) >> 1) == 0x7fffffff, "Unexpected type sign");
static_assert((uint64_t(-1) >> 1) == 0x7fffffffffffffffLL,
"Unexpected type sign");
// Assumes that an "int" is at least 32 bits.
static_assert(sizeof(int) >= 4, "Unexpected type size");
// "char" type is used to manipulate bytes. Can be signed or unsigned.
static_assert(sizeof(char) == 1, "Unexpected type size");
}
TEST(DebudNDebug, Platform) {
OZZ_IF_DEBUG(assert(true));
OZZ_IF_NDEBUG(assert(false));
}
TEST(ArraySize, Platform) {
int ai[46];
(void)ai;
static_assert(OZZ_ARRAY_SIZE(ai) == 46, "Unexpected array size");
char ac[] = "forty six";
(void)ac;
static_assert(OZZ_ARRAY_SIZE(ac) == 10, "Unexpected array size");
}
TEST(StrMatch, Platform) {
EXPECT_TRUE(ozz::strmatch("a", "a"));
EXPECT_FALSE(ozz::strmatch("a", "b"));
EXPECT_TRUE(ozz::strmatch("a", "a*"));
EXPECT_FALSE(ozz::strmatch("a", "a?"));
EXPECT_TRUE(ozz::strmatch("ab", "a?"));
EXPECT_TRUE(ozz::strmatch("ab", "?b"));
EXPECT_FALSE(ozz::strmatch("ab", "a"));
EXPECT_TRUE(ozz::strmatch("ab", "ab"));
EXPECT_TRUE(ozz::strmatch("", ""));
EXPECT_TRUE(ozz::strmatch("", "*"));
EXPECT_FALSE(ozz::strmatch("", "?"));
EXPECT_FALSE(ozz::strmatch("ab", ""));
EXPECT_FALSE(ozz::strmatch("ab", "?"));
EXPECT_TRUE(ozz::strmatch("ab", "??"));
EXPECT_TRUE(ozz::strmatch("a*b", "a*b"));
EXPECT_TRUE(ozz::strmatch("a*b", "a?b"));
EXPECT_TRUE(ozz::strmatch("ab", "ab*"));
EXPECT_TRUE(ozz::strmatch("ab", "a*"));
EXPECT_TRUE(ozz::strmatch("ab", "*b"));
EXPECT_TRUE(ozz::strmatch("ab", "a*b"));
EXPECT_TRUE(ozz::strmatch("acb", "a*b"));
EXPECT_FALSE(ozz::strmatch("abc", "a*b"));
EXPECT_TRUE(ozz::strmatch("abcdef", "a*c*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "a*c.*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "abc.def"));
EXPECT_TRUE(ozz::strmatch("abc.def", "abc.def***"));
EXPECT_FALSE(ozz::strmatch("abc.def", "abc.def?"));
EXPECT_TRUE(ozz::strmatch("abc.def", "abc?def"));
EXPECT_TRUE(ozz::strmatch("abc.def", "a*c?*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "a*.*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "a*c.*e?"));
EXPECT_TRUE(ozz::strmatch("abc.def", "*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "*.*"));
EXPECT_TRUE(ozz::strmatch("abc.def", "???.???"));
EXPECT_FALSE(ozz::strmatch("abc.def", "??.???"));
EXPECT_TRUE(ozz::strmatch("abc.def", "*??.???"));
EXPECT_TRUE(ozz::strmatch("abc.def", "*??.??*"));
EXPECT_TRUE(
ozz::strmatch("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaa",
"*a*??????a?????????a???????????????"));
}
+183
View File
@@ -0,0 +1,183 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include <stdint.h>
#include "gtest/gtest.h"
#include "ozz/base/gtest_helper.h"
#include "ozz/base/span.h"
TEST(Span, Platform) {
const size_t kSize = 46;
int i = 20;
int ai[kSize];
const size_t array_size = OZZ_ARRAY_SIZE(ai);
ozz::span<int> empty;
EXPECT_TRUE(empty.begin() == nullptr);
EXPECT_EQ(empty.size(), 0u);
EXPECT_EQ(empty.size_bytes(), 0u);
EXPECT_ASSERTION(empty[46], "Index out of range.");
ozz::span<int> single(i);
EXPECT_TRUE(single.begin() == &i);
EXPECT_EQ(single.size(), 1u);
EXPECT_EQ(single.size_bytes(), sizeof(i));
EXPECT_ASSERTION(single[46], "Index out of range.");
ozz::span<int> cs1(ai, ai + array_size);
EXPECT_EQ(cs1.begin(), ai);
EXPECT_EQ(cs1.size(), array_size);
EXPECT_EQ(cs1.size_bytes(), sizeof(ai));
// Re-inint
ozz::span<int> reinit;
reinit = ai;
EXPECT_EQ(reinit.begin(), ai);
EXPECT_EQ(reinit.size(), array_size);
EXPECT_EQ(reinit.size_bytes(), sizeof(ai));
// Clear
reinit = {};
EXPECT_EQ(reinit.size(), 0u);
EXPECT_EQ(reinit.size_bytes(), 0u);
cs1[12] = 46;
EXPECT_EQ(cs1[12], 46);
EXPECT_ASSERTION(cs1[46], "Index out of range.");
ozz::span<int> cs2(ai, array_size);
EXPECT_EQ(cs2.begin(), ai);
EXPECT_EQ(cs2.size(), array_size);
EXPECT_EQ(cs2.size_bytes(), sizeof(ai));
ozz::span<int> carray(ai);
EXPECT_EQ(carray.begin(), ai);
EXPECT_EQ(carray.size(), array_size);
EXPECT_EQ(carray.size_bytes(), sizeof(ai));
ozz::span<int> copy(cs2);
EXPECT_EQ(cs2.begin(), copy.begin());
EXPECT_EQ(cs2.size_bytes(), copy.size_bytes());
ozz::span<const int> const_copy(cs2);
EXPECT_EQ(cs2.begin(), const_copy.begin());
EXPECT_EQ(cs2.size_bytes(), const_copy.size_bytes());
EXPECT_EQ(cs2[12], 46);
EXPECT_ASSERTION(cs2[46], "Index out of range.");
// Invalid range
EXPECT_ASSERTION(ozz::span<int>(ai, ai - array_size), "Invalid range.");
}
TEST(SpanAsBytes, Platform) {
const size_t kSize = 46;
int ai[kSize];
{
ozz::span<int> si(ai);
EXPECT_EQ(si.size(), kSize);
ozz::span<const char> ab = as_bytes(si);
EXPECT_EQ(ab.size(), kSize * sizeof(int));
ozz::span<char> awb = as_writable_bytes(si);
EXPECT_EQ(awb.size(), kSize * sizeof(int));
}
{ // mutable char
char ac[kSize];
ozz::span<char> sc(ac);
EXPECT_EQ(sc.size(), kSize);
ozz::span<const char> ab = as_bytes(sc);
EXPECT_EQ(ab.size(), sc.size());
ozz::span<char> awbc = as_writable_bytes(sc);
EXPECT_EQ(awbc.size(), sc.size());
}
{ // const
ozz::span<const int> si(ai);
EXPECT_EQ(si.size(), kSize);
ozz::span<const char> ab = as_bytes(si);
EXPECT_EQ(ab.size(), kSize * sizeof(int));
}
// const char
{
const char ac[kSize] = {};
ozz::span<const char> sc(ac);
EXPECT_EQ(sc.size(), kSize);
ozz::span<const char> ab = as_bytes(sc);
EXPECT_EQ(ab.size(), sc.size());
}
}
TEST(SpanFill, Platform) {
alignas(alignof(int)) char abuffer[16];
ozz::span<char> src(abuffer);
ozz::span<int> ispan1 = ozz::fill_span<int>(src, 3);
EXPECT_EQ(ispan1.size(), 3u);
ozz::span<int> ispan2 = ozz::fill_span<int>(src, 1);
EXPECT_EQ(ispan2.size(), 1u);
EXPECT_TRUE(src.empty());
EXPECT_ASSERTION(ozz::fill_span<int>(src, 1), "Invalid range.");
// Bad aligment
src = ozz::make_span(abuffer);
ozz::span<char> cspan = ozz::fill_span<char>(src, 1);
EXPECT_EQ(cspan.size(), 1u);
EXPECT_ASSERTION(ozz::fill_span<int>(src, 1), "Invalid alignment.");
}
TEST(SpanRangeLoop, Platform) {
const size_t kSize = 46;
size_t ai[kSize];
// non const
ozz::span<size_t> si = ozz::make_span(ai);
size_t i = 0;
for (size_t& li : si) {
li = i++;
}
EXPECT_EQ(i, kSize);
// const
ozz::span<const size_t> sci = si;
i = 0;
for (const size_t& li : sci) {
EXPECT_EQ(i, li);
i++;
}
}