#include <climits>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <limits>
#include <typeinfo>
#include <zp/mem>
#include <zp/mth>
#include <zp/str>
#if !zp_std_cxx17
#error At least C++17 is required for this test!
#endif
static_assert(::zp::isptr<int>::val == false);
static_assert(::zp::isptr<int *>::val == true);
static_assert(::zp::isptr<int const *>::val == true);
static_assert(::zp::isptr<int volatile *>::val == true);
static_assert(::zp::isptr<int const volatile *>::val == true);
static_assert(::zp::isptr<int * const>::val == true);
static_assert(::zp::isptr<int const * const>::val == true);
static_assert(::zp::isptr<int volatile * const>::val == true);
static_assert(::zp::isptr<int const volatile * const>::val == true);
static_assert(::zp::isptr<int * volatile>::val == true);
static_assert(::zp::isptr<int const * volatile>::val == true);
static_assert(::zp::isptr<int volatile * volatile>::val == true);
static_assert(::zp::isptr<int const volatile * volatile>::val == true);
static_assert(::zp::isptr<int * const volatile>::val == true);
static_assert(::zp::isptr<int const * const volatile>::val == true);
static_assert(::zp::isptr<int volatile * const volatile>::val == true);
static_assert(::zp::isptr<int const volatile * const volatile>::val == true);
static_assert(::zp::typequ<int,int>::val == true);
static_assert(::zp::typequ<int,int long>::val == false);
static_assert(::zp::typequ<::zp::i8, ::std::uint8_t>::val == true);
static_assert(::zp::typequ<::zp::i8s, ::std::int8_t>::val == true);
static_assert(::zp::typequ<::zp::i01, ::std::uint16_t>::val == true);
static_assert(::zp::typequ<::zp::i01s,::std::int16_t>::val == true);
static_assert(::zp::typequ<::zp::i02, ::std::uint32_t>::val == true);
static_assert(::zp::typequ<::zp::i02s,::std::int32_t>::val == true);
static_assert(::zp::typequ<::zp::i04, ::std::uint64_t>::val == true);
static_assert(::zp::typequ<::zp::i04s,::std::int64_t>::val == true);
static_assert(::zp::typequ<::zp::ptr, ::std::uintptr_t>::val == true);
static_assert(::zp::typequ<::zp::ptrdif,::std::ptrdiff_t>::val == true);
static_assert(::zp::typequ<::zp::siz, ::std::size_t>::val == true);
static_assert(::zp::typequ<::zp::remref<int>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remref<int &>::typ,int>::val == true);
static_assert(::zp::typequ<::zp::remptr<int>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remptr<int *>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remptr<int * const>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remptr<int * volatile>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remptr<int * const volatile>::typ,int>::val == true);
static_assert(::zp::typequ<::zp::remqual<int>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remqual<int const>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remqual<int volatile>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::remqual<int const volatile>::typ,int>::val == true);
static_assert(::zp::typequ<::zp::sgn<int>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::sgn<int const>::typ, int const>::val == true);
static_assert(::zp::typequ<::zp::sgn<int volatile>::typ, int volatile>::val == true);
static_assert(::zp::typequ<::zp::sgn<int const volatile>::typ, int const volatile>::val == true);
static_assert(::zp::typequ<::zp::sgn<int unsigned>::typ, int>::val == true);
static_assert(::zp::typequ<::zp::sgn<int unsigned const>::typ, int const>::val == true);
static_assert(::zp::typequ<::zp::sgn<int unsigned volatile>::typ, int volatile>::val == true);
static_assert(::zp::typequ<::zp::sgn<int unsigned const volatile>::typ,int const volatile>::val == true);
static_assert(::zp::typequ<::zp::usgn<int unsigned>::typ, int unsigned>::val == true);
static_assert(::zp::typequ<::zp::usgn<int unsigned const>::typ, int unsigned const>::val == true);
static_assert(::zp::typequ<::zp::usgn<int unsigned volatile>::typ, int unsigned volatile>::val == true);
static_assert(::zp::typequ<::zp::usgn<int unsigned const volatile>::typ,int unsigned const volatile>::val == true);
static_assert(::zp::typequ<::zp::usgn<int>::typ, int unsigned>::val == true);
static_assert(::zp::typequ<::zp::usgn<int const>::typ, int unsigned const>::val == true);
static_assert(::zp::typequ<::zp::usgn<int volatile>::typ, int unsigned volatile>::val == true);
static_assert(::zp::typequ<::zp::usgn<int const volatile>::typ, int unsigned const volatile>::val == true);
static_assert(::zp::typequ<::zp::nulptrtyp,::std::nullptr_t>::val == true);
static_assert(::zp::isusgn<char>::val == ::std::is_unsigned<char>::value);
static_assert(::zp::isusgn<char16_t>::val == ::std::is_unsigned<char16_t>::value);
static_assert(::zp::isusgn<char32_t>::val == ::std::is_unsigned<char32_t>::value);
static_assert(::zp::isusgn<::zp::c8>::val == ::std::is_unsigned<::zp::c8>::value);
static_assert(::zp::isusgn<double>::val == ::std::is_unsigned<double>::value);
static_assert(::zp::isusgn<float>::val == ::std::is_unsigned<float>::value);
static_assert(::zp::isusgn<int>::val == ::std::is_unsigned<int>::value);
static_assert(::zp::isusgn<int long>::val == ::std::is_unsigned<int long>::value);
static_assert(::zp::isusgn<double long>::val == ::std::is_unsigned<double long>::value);
static_assert(::zp::isusgn<int long long>::val == ::std::is_unsigned<int long long>::value);
static_assert(::zp::isusgn<int short>::val == ::std::is_unsigned<int short>::value);
static_assert(::zp::isusgn<char signed>::val == ::std::is_unsigned<char signed>::value);
static_assert(::zp::isusgn<char unsigned>::val == ::std::is_unsigned<char unsigned>::value);
static_assert(::zp::isusgn<int unsigned>::val == ::std::is_unsigned<int unsigned>::value);
static_assert(::zp::isusgn<int long unsigned>::val == ::std::is_unsigned<int long unsigned>::value);
static_assert(::zp::isusgn<int long long unsigned>::val == ::std::is_unsigned<int long long unsigned>::value);
static_assert(::zp::isusgn<int short unsigned>::val == ::std::is_unsigned<int short unsigned>::value);
static_assert(::zp::isusgn<wchar_t>::val == ::std::is_unsigned<wchar_t>::value);
static_assert(::zp::issgn<char>::val == ::std::is_signed<char>::value);
static_assert(::zp::issgn<double>::val == ::std::is_signed<double>::value);
static_assert(::zp::issgn<float>::val == ::std::is_signed<float>::value);
static_assert(::zp::issgn<int>::val == ::std::is_signed<int>::value);
static_assert(::zp::issgn<int long>::val == ::std::is_signed<int long>::value);
static_assert(::zp::issgn<double long>::val == ::std::is_signed<double long>::value);
static_assert(::zp::issgn<int long long>::val == ::std::is_signed<int long long>::value);
static_assert(::zp::issgn<int short>::val == ::std::is_signed<int short>::value);
static_assert(::zp::issgn<char signed>::val == ::std::is_signed<char signed>::value);
static_assert(::zp::issgn<char unsigned>::val == ::std::is_signed<char unsigned>::value);
static_assert(::zp::issgn<int unsigned>::val == ::std::is_signed<int unsigned>::value);
static_assert(::zp::issgn<int long unsigned>::val == ::std::is_signed<int long unsigned>::value);
static_assert(::zp::issgn<int long long unsigned>::val == ::std::is_signed<int long long unsigned>::value);
static_assert(::zp::issgn<int short unsigned>::val == ::std::is_signed<int short unsigned>::value);
static_assert(::zp::issgn<wchar_t>::val == ::std::is_signed<wchar_t>::value);
static_assert(::zp::bytelen == CHAR_BIT);
static_assert(::zp::minval<bool>::val == ::std::numeric_limits<bool>::lowest());
static_assert(::zp::minval<char>::val == ::std::numeric_limits<char>::lowest());
static_assert(::zp::minval<char16_t>::val == ::std::numeric_limits<char16_t>::lowest());
static_assert(::zp::minval<char32_t>::val == ::std::numeric_limits<char32_t>::lowest());
static_assert(::zp::minval<::zp::c8>::val == ::std::numeric_limits<::zp::c8>::lowest());
static_assert(::zp::minval<double>::val == ::std::numeric_limits<double>::lowest());
static_assert(::zp::minval<float>::val == ::std::numeric_limits<float>::lowest());
static_assert(::zp::minval<int>::val == ::std::numeric_limits<int>::lowest());
static_assert(::zp::minval<int long>::val == ::std::numeric_limits<int long>::lowest());
static_assert(::zp::minval<double long>::val == ::std::numeric_limits<double long>::lowest());
static_assert(::zp::minval<int long long>::val == ::std::numeric_limits<int long long>::lowest());
static_assert(::zp::minval<int short>::val == ::std::numeric_limits<int short>::lowest());
static_assert(::zp::minval<char signed>::val == ::std::numeric_limits<char signed>::lowest());
static_assert(::zp::minval<char unsigned>::val == ::std::numeric_limits<char unsigned>::lowest());
static_assert(::zp::minval<int short unsigned>::val == ::std::numeric_limits<int short unsigned>::lowest());
static_assert(::zp::minval<int unsigned>::val == ::std::numeric_limits<int unsigned>::lowest());
static_assert(::zp::minval<int long unsigned>::val == ::std::numeric_limits<int long unsigned>::lowest());
static_assert(::zp::minval<int long long unsigned>::val == ::std::numeric_limits<int long long unsigned>::lowest());
static_assert(::zp::minval<wchar_t>::val == ::std::numeric_limits<wchar_t>::lowest());
static_assert(::zp::maxval<bool>::val == ::std::numeric_limits<bool>::max());
static_assert(::zp::maxval<char>::val == ::std::numeric_limits<char>::max());
static_assert(::zp::maxval<char16_t>::val == ::std::numeric_limits<char16_t>::max());
static_assert(::zp::maxval<char32_t>::val == ::std::numeric_limits<char32_t>::max());
static_assert(::zp::maxval<::zp::c8>::val == ::std::numeric_limits<::zp::c8>::max());
static_assert(::zp::maxval<double>::val == ::std::numeric_limits<double>::max());
static_assert(::zp::maxval<float>::val == ::std::numeric_limits<float>::max());
static_assert(::zp::maxval<int>::val == ::std::numeric_limits<int>::max());
static_assert(::zp::maxval<int long>::val == ::std::numeric_limits<int long>::max());
static_assert(::zp::maxval<double long>::val == ::std::numeric_limits<double long>::max());
static_assert(::zp::maxval<int long long>::val == ::std::numeric_limits<int long long>::max());
static_assert(::zp::maxval<int short>::val == ::std::numeric_limits<int short>::max());
static_assert(::zp::maxval<char signed>::val == ::std::numeric_limits<char signed>::max());
static_assert(::zp::maxval<char unsigned>::val == ::std::numeric_limits<char unsigned>::max());
static_assert(::zp::maxval<int short unsigned>::val == ::std::numeric_limits<int short unsigned>::max());
static_assert(::zp::maxval<int unsigned>::val == ::std::numeric_limits<int unsigned>::max());
static_assert(::zp::maxval<int long unsigned>::val == ::std::numeric_limits<int long unsigned>::max());
static_assert(::zp::maxval<int long long unsigned>::val == ::std::numeric_limits<int long long unsigned>::max());
static_assert(::zp::maxval<wchar_t>::val == ::std::numeric_limits<wchar_t>::max());
template<typename ltyp,typename rtyp> static auto cmp(int unsigned & numerr,int long const ln,ltyp const & lvalref,rtyp const & rvalref) noexcept {
char const* const ltypnm = typeid (ltyp).name();
char const* const rtypnm = typeid (rtyp).name();
auto const getval = [](auto const & valref) {
using typ = typename ::zp::remqual<typename ::zp::remref<decltype (valref)>::typ>::typ;
if constexpr (::zp::ischrtyp<typ>::val) {return static_cast<::zp::i02>(valref);}
else if constexpr (::zp::isptr<typ>::val) {return reinterpret_cast<void *>(valref);}
else {return valref;}
};
auto const lval = getval(lvalref);
auto const rval = getval(rvalref);
::std::cout << " " << ln << ". comparing " << ltypnm << " (" << lval << ") vs. " << rtypnm << " (" << rval << ")... ";
if (lval != rval) {
::std::cout << "\x1B[38;5;161munequal\x1B[0m\n";
//throw ::std::exception {};
++numerr;
return;
}
::std::cout <<"\x1B[38;5;77mequal\x1B[0m\n";
}
#define cmp(lval,rval) (::cmp(numerr,__LINE__,(lval),(rval)))
int main() {
int unsigned numerr = 0x0u;
auto const tst = [](char const* const tst) noexcept {
::std::cout <<"\n\x1B[38;5;75mtesting\x1B[0m " << tst <<"\n\n";
};
::std::cout <<"zp " <<::zp::ver.api <<"." <<::zp::ver.ext <<", run-time test\n";
try {
#if false
[&] {
tst("optionals");
::zp::opt<::zp::i8s> opt = ::zp::nulopt;
cmp(opt.chk(),false);
auto const fun = [](char const* msg) -> void {
::std::cout << msg << ::std::endl;
::std::abort();
};
opt = -0x45;
cmp(opt.chk(),true);
cmp(opt.exp(fun,"expectation failed"),-0x45);
}();
#endif
[&] {
tst("special numbers");
::zp::f02 f02;
::zp::f04 f04;
cmp(sizeof (f02),0x4u);
cmp(sizeof (f04),0x8u);
f02 = ::zp::nan<::zp::f02>::val;
f04 = ::zp::nan<::zp::f04>::val;
cmp(::zp::isnan(f02),true);
cmp(::zp::isnan(f04),true);
f02 = ::zp::inf<::zp::f02>::val;
f04 = ::zp::inf<::zp::f04>::val;
cmp(f02 > ::zp::maxval<::zp::f02>::val,true);
cmp(f04 > ::zp::maxval<::zp::f04>::val,true);
}();
[&] {
tst("mathematics");
}();
/*[&] {
tst("vectors");
::zp::vec2<int> const lvec2 = {
.x = +0x1,
.y = -0x3,
};
::zp::vec2<int> const rvec2 = {
.x = +0x2,
.y = -0x4,
};
cmp(::zp::dot(lvec2,rvec2),0xE);
::zp::vec3<int> const lvec3 = {
.x = +0x1,
.y = -0x3,
.z = +0x5,
};
::zp::vec3<int> const rvec3 = {
.x = +0x2,
.y = -0x4,
.z = +0x6,
};
cmp(::zp::dot(lvec3,rvec3),0x2C);
::zp::vec4<int> const lvec4 = {
.x = +0x1,
.y = -0x3,
.z = +0x5,
.w = -0x7,
};
::zp::vec4<int> const rvec4 = {
.x = +0x2,
.y = -0x4,
.z = +0x6,
.w = -0x8,
};
cmp(::zp::dot(lvec4,rvec4),0x64);
auto const avec2 = ::zp::vadd(lvec2,rvec2);
auto const svec2 = ::zp::vsub(lvec2,rvec2);
cmp(avec2.x,+0x3);
cmp(avec2.y,-0x7);
cmp(svec2.x,-0x1);
cmp(svec2.y,+0x1);
}();*/
[&] {
tst("memory sequences");
::zp::i04 filbuf;
cmp(::zp::memfil(&filbuf,0xFFu,0x8u),reinterpret_cast<char unsigned *>(&filbuf)+0x8u);
cmp(::zp::memfil(&filbuf,0x7Fu,0x4u),reinterpret_cast<char unsigned *>(&filbuf)+0x4u);
cmp(::zp::memfil(&filbuf,0x3Fu,0x2u),reinterpret_cast<char unsigned *>(&filbuf)+0x2u);
cmp(::zp::memfil(&filbuf,0x1Fu,0x1u),reinterpret_cast<char unsigned *>(&filbuf)+0x1u);
cmp(filbuf,0xFFFFFFFF7F7F3F1Fu);
::zp::i04 cpybuf;
::zp::memcpy(&cpybuf,&filbuf,0x8u);
cmp(cpybuf,filbuf);
cmp(::zp::memsrh(&cpybuf,0x1Fu,0x8u),reinterpret_cast<char unsigned *>(&cpybuf));
}();
[&] {
tst("strings");
char str[] = "Hello there!";
wchar_t wstr[] = L"Hello there!";
char32_t str02[] = U"Hello there!";
::zp::siz const len = ::zp_strlen( str);
::zp::siz const wlen = ::zp_wstrlen( wstr);
::zp::siz const len02 = ::zp_utf32len(str02);
cmp(len, 0xCu);
cmp(wlen, 0xCu);
cmp(len02,0xCu);
auto const buf = new char[ len];
auto const wbuf = new wchar_t[ wlen];
auto const buf02 = new char32_t[len02];
cmp(::zp_strcpy( buf, str), len);
cmp(::zp_wstrcpy( wbuf, wstr), wlen);
cmp(::zp_utf32cpy(buf02,str02),len02);
delete[] buf;
delete[] wbuf;
delete[] buf02;
}();
[&] {
tst("UTF-8");
char32_t const src[] = U"\U0001F480";
::zp::siz const buf8len = ::zp_utf8enclen(src);
cmp(buf8len,0x4u);
::zp::c8 * buf8 = new ::zp::c8[buf8len+0x1];
::zp_utf8enc(buf8,src);
cmp(buf8[0x0],0xF0u);
cmp(buf8[0x1],0x9Fu);
cmp(buf8[0x2],0x92u);
cmp(buf8[0x3],0x80u);
cmp(buf8[0x4],0x00u);
::zp::siz const buf02len = ::zp_utf8declen(buf8);
cmp(buf02len,0x1u);
char32_t * buf02 = new char32_t[buf02len+0x1];
::zp_utf8dec(buf02,buf8);
cmp(buf02[0x0],0x1F480u);
cmp(buf02[0x1],0x0u);
delete[] buf8;
delete[] buf02;
}();
[&] {
tst("UTF-16");
char32_t const src[] = U"\U0001F480\u00F0";
::zp::siz const buf01len = ::zp_utf16enclen(src);
cmp(buf01len,0x3u);
char16_t * buf01 = new char16_t[buf01len+0x1];
::zp_utf16enc(buf01,src);
cmp(buf01[0x0],0xD83Du);
cmp(buf01[0x1],0xDC80u);
cmp(buf01[0x2],0x00F0u);
cmp(buf01[0x3],0x0000u);
::zp::siz const buf02len = ::zp_utf16declen(buf01);
cmp(buf02len,0x2u);
char32_t * buf02 = new char32_t[buf02len+0x1];
::zp_utf16dec(buf02,buf01);
cmp(buf02[0x0],0x1F480u);
cmp(buf02[0x1],0xF0u);
cmp(buf02[0x2],0x0u);
delete[] buf01;
delete[] buf02;
}();
}
catch (::std::exception const &) {
return EXIT_FAILURE;
}
::std::cout <<"\nDone \u2212 " <<numerr <<" error(s)\n";
return numerr ? EXIT_FAILURE : EXIT_SUCCESS;
}