Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9bb2bdbaba
@ -26,11 +26,11 @@ endif()
|
||||
|
||||
|
||||
###############################################################################
|
||||
RAGEL_TARGET(json-flat json/flat.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/json/flat.cpp)
|
||||
RAGEL_TARGET(uri uri.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/uri.cpp)
|
||||
RAGEL_TARGET(json-flat json/flat.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/json/flat.cpp COMPILE_FLAGS -G2)
|
||||
RAGEL_TARGET(uri uri.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/uri.cpp COMPILE_FLAGS -G2)
|
||||
RAGEL_TARGET(version version.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/version.cpp)
|
||||
RAGEL_TARGET(format.cpp format.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/format.cpp)
|
||||
|
||||
RAGEL_TARGET(parse8601 time/parse8601.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/time/parse8601.cpp)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
||||
@ -76,16 +76,6 @@ else ()
|
||||
endif ()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# platform libraries
|
||||
search_libs (SHM_LIBS shm_open rt)
|
||||
search_libs (DL_LIBS dlopen dl)
|
||||
search_libs (CLOCK_LIB clock_gettime rt c)
|
||||
search_libs (MATH_LIB cos m)
|
||||
|
||||
list (APPEND LIBS ${SHM_LIBS} ${DL_LIBS} ${CLOCK_LIB} ${MATH_LIB})
|
||||
|
||||
|
||||
###############################################################################
|
||||
# platform wrappers
|
||||
list (
|
||||
@ -93,8 +83,12 @@ list (
|
||||
posix/dir.cpp
|
||||
posix/dir.hpp
|
||||
posix/dir.ipp
|
||||
posix/except.cpp
|
||||
posix/except.hpp
|
||||
posix/fd.cpp
|
||||
posix/fd.hpp
|
||||
posix/socket.cpp
|
||||
posix/socket.hpp
|
||||
)
|
||||
|
||||
|
||||
@ -133,6 +127,8 @@ if (WINDOWS)
|
||||
library_win32.hpp
|
||||
library_win32.cpp
|
||||
time_win32.cpp
|
||||
win32/except.cpp
|
||||
win32/except.hpp
|
||||
win32/handle.cpp
|
||||
win32/handle.hpp
|
||||
win32/registry.hpp
|
||||
@ -194,9 +190,9 @@ list (
|
||||
coord.hpp
|
||||
coord/init.hpp
|
||||
coord/iostream.hpp
|
||||
coord/names.hpp
|
||||
coord/ops.hpp
|
||||
coord/store.hpp
|
||||
coord/traits.hpp
|
||||
crypto/arc4.cpp
|
||||
crypto/arc4.hpp
|
||||
crypto/ice.cpp
|
||||
@ -212,10 +208,10 @@ list (
|
||||
debug.cpp
|
||||
debug.hpp
|
||||
debug.ipp
|
||||
encode/base.cpp
|
||||
encode/base.hpp
|
||||
endian.cpp
|
||||
endian.hpp
|
||||
except.cpp
|
||||
except.hpp
|
||||
exe.hpp
|
||||
extent.cpp
|
||||
extent.hpp
|
||||
@ -341,7 +337,6 @@ list (
|
||||
matrix3.cpp
|
||||
matrix4.cpp
|
||||
matrix.hpp
|
||||
matrix.ipp
|
||||
memory/deleter.cpp
|
||||
memory/deleter.hpp
|
||||
nocopy.hpp
|
||||
@ -406,7 +401,8 @@ list (
|
||||
term.hpp
|
||||
time.cpp
|
||||
time.hpp
|
||||
time.ipp
|
||||
time/parse.hpp
|
||||
time/parse8601.cpp
|
||||
tuple.cpp
|
||||
tuple.hpp
|
||||
typeidx.cpp
|
||||
@ -453,7 +449,20 @@ DEPENDS
|
||||
|
||||
###############################################################################
|
||||
add_library(cruft-util ${UTIL_FILES})
|
||||
target_link_libraries (cruft-util ${LIBS})
|
||||
target_link_libraries (cruft-util PUBLIC ${LIBS})
|
||||
target_include_directories(cruft-util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
###############################################################################
|
||||
# platform libraries
|
||||
search_libs (SHM_LIBS shm_open rt)
|
||||
search_libs (DL_LIBS dlopen dl)
|
||||
search_libs (CLOCK_LIBS clock_gettime rt c)
|
||||
search_libs (MATH_LIBS cos m)
|
||||
|
||||
target_link_libraries(cruft-util PUBLIC ${SHM_LIBS})
|
||||
target_link_libraries(cruft-util PUBLIC ${DL_LIBS})
|
||||
target_link_libraries(cruft-util PUBLIC ${CLOCK_LIBS})
|
||||
target_link_libraries(cruft-util PUBLIC ${MATH_LIBS})
|
||||
|
||||
|
||||
###############################################################################
|
||||
@ -461,6 +470,7 @@ foreach (tool hash json-clean json-schema json-validate scratch)
|
||||
add_executable (util_${tool} tools/${tool}.cpp)
|
||||
set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool})
|
||||
target_link_libraries (util_${tool} cruft-util)
|
||||
target_include_directories(util_${tool} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endforeach ()
|
||||
|
||||
|
||||
@ -494,6 +504,7 @@ if (TESTS)
|
||||
crypto/tea
|
||||
crypto/xtea
|
||||
crypto/xxtea
|
||||
encode/base
|
||||
endian
|
||||
exe
|
||||
extent
|
||||
@ -542,8 +553,9 @@ if (TESTS)
|
||||
string
|
||||
stringid
|
||||
strongdef
|
||||
tuple
|
||||
time/8601
|
||||
traits
|
||||
tuple
|
||||
typeidx
|
||||
uri
|
||||
utf8
|
||||
@ -556,6 +568,7 @@ if (TESTS)
|
||||
string(REPLACE "/" "_" name "test/${t}")
|
||||
add_executable(util_${name} test/${t}.cpp)
|
||||
target_link_libraries(util_${name} PRIVATE cruft-util)
|
||||
target_include_directories(util_${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_test(NAME util_${name} COMMAND util_${name})
|
||||
endforeach(t)
|
||||
endif ()
|
||||
|
67
abnf.rl
Normal file
67
abnf.rl
Normal file
@ -0,0 +1,67 @@
|
||||
void foo (void) { }
|
||||
|
||||
%%{
|
||||
|
||||
machine rfc5234;
|
||||
|
||||
###############################################################################
|
||||
# RFC5234 ABNF core rules
|
||||
|
||||
# ; A-Z / a-z
|
||||
ALPHA = 0x41..0x5A | 0x61..0x7A;
|
||||
BIT = '0' | '1';
|
||||
|
||||
# any 7-bit US-ASCII character, excluding NUL
|
||||
CHAR = 0x01..0x7F;
|
||||
|
||||
# carriage return
|
||||
CR = 0x0D;
|
||||
|
||||
# linefeed
|
||||
LF = 0x0A;
|
||||
|
||||
# Internet standard newline
|
||||
CRLF = CR LF;
|
||||
|
||||
# controls
|
||||
CTL = 0x00..0x1F | 0x7F;
|
||||
|
||||
# 0-9
|
||||
DIGIT = 0x30..0x39;
|
||||
|
||||
# " (Double Quote)
|
||||
DQUOTE = 0x22;
|
||||
|
||||
HEXDIG = DIGIT | 'A'..'F';
|
||||
|
||||
# horizontal tab
|
||||
HTAB = 0x09;
|
||||
|
||||
SP = 0x20;
|
||||
|
||||
# white space
|
||||
WSP = SP | HTAB;
|
||||
|
||||
# Use of this linear-white-space rule permits lines containing only white space
|
||||
# that are no longer legal in mail headers and have caused interoperability
|
||||
# problems in other contexts.
|
||||
#
|
||||
# Do not use when defining mail headers and use with caution in other contexts.
|
||||
LWSP = (WSP | CRLF WSP)*;
|
||||
|
||||
# 8 bits of data
|
||||
OCTET = any; #0x00..0xFF;
|
||||
|
||||
# visible (printing) characters
|
||||
VCHAR = 0x21..0x7E;
|
||||
|
||||
write data;
|
||||
|
||||
}%%
|
||||
|
||||
int main () {
|
||||
|
||||
|
||||
%%write init;
|
||||
%%write exec;
|
||||
}
|
@ -44,6 +44,6 @@ namespace cruft::util::sort {
|
||||
soa (RandomIt key_first, RandomIt key_last, Comparator comp, Args ...values);
|
||||
}
|
||||
|
||||
#include "./sort.ipp"
|
||||
#include "sort.ipp"
|
||||
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
#include "./allocator.hpp"
|
||||
#include "allocator.hpp"
|
||||
|
@ -38,6 +38,6 @@ namespace util::alloc {
|
||||
};
|
||||
}
|
||||
|
||||
#include "./allocator.ipp"
|
||||
#include "allocator.ipp"
|
||||
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
#include "./arena.hpp"
|
||||
#include "arena.hpp"
|
||||
|
@ -68,6 +68,6 @@ namespace util::alloc {
|
||||
};
|
||||
}
|
||||
|
||||
#include "./arena.ipp"
|
||||
#include "arena.ipp"
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./affix.hpp"
|
||||
#include "affix.hpp"
|
||||
|
||||
using util::alloc::raw::affix;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./linear.hpp"
|
||||
#include "linear.hpp"
|
||||
|
||||
#include "../../pointer.hpp"
|
||||
#include "../../debug.hpp"
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./malloc.hpp"
|
||||
#include "malloc.hpp"
|
||||
|
||||
#include "../../debug.hpp"
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "./null.hpp"
|
||||
#include "null.hpp"
|
||||
|
||||
#include "../../debug.hpp"
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./stack.hpp"
|
||||
#include "stack.hpp"
|
||||
|
||||
#include "../../debug.hpp"
|
||||
#include "../../pointer.hpp"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef __CRUFT_UTIL_ASCII_HPP
|
||||
#define __CRUFT_UTIL_ASCII_HPP
|
||||
|
||||
#include "./annotation.hpp"
|
||||
#include "annotation.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
@ -77,7 +77,7 @@ namespace util::ascii {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
constexpr inline
|
||||
unsigned
|
||||
uint8_t
|
||||
from_hex (char c)
|
||||
{
|
||||
return c >= '0' && c <= '9' ? (c - '0' ) :
|
||||
|
@ -17,10 +17,10 @@
|
||||
|
||||
#include "backtrace.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./exe.hpp"
|
||||
#include "./io.hpp"
|
||||
#include "./cast.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "exe.hpp"
|
||||
#include "io.hpp"
|
||||
#include "cast.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
@ -14,11 +14,12 @@
|
||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./backtrace.hpp"
|
||||
#include "backtrace.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./except.hpp"
|
||||
#include "./types.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "except.hpp"
|
||||
#include "types.hpp"
|
||||
#include "win32/error.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
@ -66,7 +67,7 @@ backtrace::backtrace ()
|
||||
SymGetModuleBase64,
|
||||
nullptr))
|
||||
{
|
||||
util::win32_error::throw_code ();
|
||||
util::win32::error::throw_code ();
|
||||
}
|
||||
|
||||
// we've read the bottom of the stack
|
||||
|
@ -15,11 +15,12 @@
|
||||
* 2012-2016, Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./backtrace.hpp"
|
||||
#include "backtrace.hpp"
|
||||
|
||||
#include "./win32/handle.hpp"
|
||||
#include "./debug.hpp"
|
||||
#include "./except.hpp"
|
||||
#include "win32/error.hpp"
|
||||
#include "win32/handle.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "except.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <windows.h>
|
||||
@ -33,7 +34,7 @@ debug::backtrace::backtrace (void)
|
||||
|
||||
auto process = GetCurrentProcess();
|
||||
if (!SymInitialize (process, NULL, TRUE))
|
||||
util::win32_error::throw_code ();
|
||||
util::win32::error::throw_code ();
|
||||
|
||||
while (true) {
|
||||
auto res = CaptureStackBackTrace (1, m_frames.size (), m_frames.data (), NULL);
|
||||
|
10
bezier.cpp
10
bezier.cpp
@ -14,12 +14,12 @@
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./bezier.hpp"
|
||||
#include "bezier.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./polynomial.hpp"
|
||||
#include "./stream.hpp"
|
||||
#include "./coord/iostream.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "polynomial.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "coord/iostream.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./bezier.hpp"
|
||||
#include "bezier.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
@ -14,10 +14,10 @@
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./bezier.hpp"
|
||||
#include "bezier.hpp"
|
||||
|
||||
#include "./polynomial.hpp"
|
||||
#include "./coord/iostream.hpp"
|
||||
#include "polynomial.hpp"
|
||||
#include "coord/iostream.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./bezier.hpp"
|
||||
#include "bezier.hpp"
|
||||
|
||||
#include "coord/iostream.hpp"
|
||||
|
||||
@ -30,10 +30,10 @@ namespace util {
|
||||
CHECK_GE (t, 0);
|
||||
CHECK_LE (t, 1);
|
||||
|
||||
auto v0 = pow (1 - t, 3) * m_points[0];
|
||||
auto v0 = pow (1 - t, 3u) * m_points[0];
|
||||
auto v1 = 3 * pow2 (1 - t) * t * m_points[1];
|
||||
auto v2 = 3 * pow2 (1 - t) * t * m_points[2];
|
||||
auto v3 = pow (t, 3) * m_points[3];
|
||||
auto v3 = pow (t, 3u) * m_points[3];
|
||||
|
||||
return {
|
||||
v0.x + v1.x + v2.x + v3.x,
|
||||
|
2
cast.hpp
2
cast.hpp
@ -17,7 +17,7 @@
|
||||
#ifndef __UTIL_CAST_HPP
|
||||
#define __UTIL_CAST_HPP
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
|
18
cmdopt.cpp
18
cmdopt.cpp
@ -14,10 +14,10 @@
|
||||
* Copyright 2013-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./cmdopt.hpp"
|
||||
#include "cmdopt.hpp"
|
||||
|
||||
#include "./cast.hpp"
|
||||
#include "./debug.hpp"
|
||||
#include "cast.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
@ -192,27 +192,27 @@ suffix_to_multiplier (char c)
|
||||
switch (c) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
return util::pow (1024UL, 6);
|
||||
return util::pow (1024UL, 6u);
|
||||
|
||||
case 'p':
|
||||
case 'P':
|
||||
return util::pow (1024UL, 5);
|
||||
return util::pow (1024UL, 5u);
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
return util::pow (1024UL, 4);
|
||||
return util::pow (1024UL, 4u);
|
||||
|
||||
case 'g':
|
||||
case 'G':
|
||||
return util::pow (1024UL, 3);
|
||||
return util::pow (1024UL, 3u);
|
||||
|
||||
case 'm':
|
||||
case 'M':
|
||||
return util::pow (1024UL, 2);
|
||||
return util::pow (1024UL, 2u);
|
||||
|
||||
case 'k':
|
||||
case 'K':
|
||||
return util::pow (1024UL, 1);
|
||||
return util::pow (1024UL, 1u);
|
||||
|
||||
default:
|
||||
const char str[2] = { c, '\0' };
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
#include "./introspection.hpp"
|
||||
#include "./iterator.hpp"
|
||||
#include "introspection.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace util::cmdopt {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
463
colour.cpp
463
colour.cpp
@ -14,454 +14,45 @@
|
||||
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./colour.hpp"
|
||||
#include "colour.hpp"
|
||||
|
||||
#include "./ascii.hpp"
|
||||
#include "./debug.hpp"
|
||||
#include "./log.hpp"
|
||||
#include "./range.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
using util::colour;
|
||||
using util::colour3f;
|
||||
using util::colour4f;
|
||||
#include "ascii.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
colour<S,T>
|
||||
colour<S,T>::parse_html (const char *fmt)
|
||||
static util::srgba4f
|
||||
parse_hex (util::view<const char*> str)
|
||||
{
|
||||
// ensure the format is the correct length
|
||||
auto len = strlen (fmt);
|
||||
if (str.size () != strlen ("#012345"))
|
||||
throw std::invalid_argument ("expected length of 7");
|
||||
|
||||
switch (len) {
|
||||
case 1 + 2 * S:
|
||||
if (*fmt != '#')
|
||||
throw std::invalid_argument ("missing leading hash");
|
||||
++fmt;
|
||||
break;
|
||||
if (str[0] != '#')
|
||||
throw std::invalid_argument ("expected leading '#'");
|
||||
|
||||
case 2 * S:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument ("format is the wrong length");
|
||||
if (!util::ascii::is_hex (str[1]) ||
|
||||
!util::ascii::is_hex (str[2]) ||
|
||||
!util::ascii::is_hex (str[3]) ||
|
||||
!util::ascii::is_hex (str[4]) ||
|
||||
!util::ascii::is_hex (str[5]) ||
|
||||
!util::ascii::is_hex (str[6]))
|
||||
{
|
||||
throw std::invalid_argument ("expected hex digits");
|
||||
}
|
||||
|
||||
// parse the octets
|
||||
util::colour<S,uint8_t> res;
|
||||
for (size_t i = 0; i < res.size (); ++i) {
|
||||
auto a = util::ascii::from_hex (fmt[i*2+0]);
|
||||
auto b = util::ascii::from_hex (fmt[i*2+1]);
|
||||
uint8_t r = util::ascii::from_hex (str[1]) << 4u | util::ascii::from_hex (str[2]);
|
||||
uint8_t g = util::ascii::from_hex (str[3]) << 4u | util::ascii::from_hex (str[4]);
|
||||
uint8_t b = util::ascii::from_hex (str[5]) << 4u | util::ascii::from_hex (str[6]);
|
||||
|
||||
res[i] = (a << 4u) | b;
|
||||
}
|
||||
|
||||
return res.template cast<T> ();
|
||||
return util::srgba<4,uint8_t> { r, g, b, 255 }.template cast<float> ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const std::map<std::string, colour<4,uint8_t>>
|
||||
HTML_COLOURS { {
|
||||
{ "white", { 0xff, 0xff, 0xff, 0xff } },
|
||||
{ "silver", { 0xc0, 0xc0, 0xc0, 0xff } },
|
||||
{ "gray", { 0x80, 0x80, 0x80, 0xff } },
|
||||
{ "black", { 0x00, 0x00, 0x00, 0xff } },
|
||||
{ "red", { 0xff, 0x00, 0x00, 0xff } },
|
||||
{ "maroon", { 0x80, 0x00, 0x00, 0xff } },
|
||||
{ "yellow", { 0xff, 0xff, 0x00, 0xff } },
|
||||
{ "olive", { 0x80, 0x80, 0x00, 0xff } },
|
||||
{ "lime", { 0x00, 0xff, 0x00, 0xff } },
|
||||
{ "green", { 0x00, 0x80, 0x00, 0xff } },
|
||||
{ "aqua", { 0x00, 0xff, 0xff, 0xff } },
|
||||
{ "teal", { 0x00, 0x80, 0x80, 0xff } },
|
||||
{ "blue", { 0x00, 0x00, 0xff, 0xff } },
|
||||
{ "navy", { 0x00, 0x00, 0x80, 0xff } },
|
||||
{ "fuchsia", { 0xff, 0x00, 0xff, 0xff } },
|
||||
{ "purple", { 0x80, 0x00, 0x80, 0xff } },
|
||||
} };
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::map<std::string, colour<4,uint8_t>> X11_COLOURS
|
||||
template <>
|
||||
util::srgba4f
|
||||
util::parse<util::srgba4f> (util::view<const char*> str)
|
||||
{
|
||||
/* pink */
|
||||
{ "pink", { 0xff, 0xc0, 0xcb, 0xff } },
|
||||
{ "lightpink", { 0xff, 0xb6, 0xc1, 0xff } },
|
||||
{ "hotpink", { 0xff, 0x69, 0xb4, 0xff } },
|
||||
{ "deeppink", { 0xff, 0x14, 0x93, 0xff } },
|
||||
{ "palevioletred", { 0xdb, 0x70, 0x93, 0xff } },
|
||||
{ "mediumvioletred", { 0xc7, 0x15, 0x85, 0xff } },
|
||||
|
||||
/* red */
|
||||
{ "lightsalmon", { 0xff, 0xa0, 0x7a, 0xff } },
|
||||
{ "salmon", { 0xfa, 0x80, 0x72, 0xff } },
|
||||
{ "darksalmon", { 0xe9, 0x96, 0x7a, 0xff } },
|
||||
{ "lightcoral", { 0xf0, 0x80, 0x80, 0xff } },
|
||||
{ "indianred", { 0xcd, 0x5c, 0x5c, 0xff } },
|
||||
{ "crimson", { 0xdc, 0x14, 0x3c, 0xff } },
|
||||
{ "firebrick", { 0xb2, 0x22, 0x22, 0xff } },
|
||||
{ "darkred", { 0x8b, 0x00, 0x00, 0xff } },
|
||||
{ "red", { 0xff, 0x00, 0x00, 0xff } },
|
||||
|
||||
/* orange */
|
||||
{ "orangered", { 0xff, 0x45, 0x00, 0xff } },
|
||||
{ "tomato", { 0xff, 0x63, 0x47, 0xff } },
|
||||
{ "coral", { 0xff, 0x7f, 0x50, 0xff } },
|
||||
{ "darkorange", { 0xff, 0x8c, 0x00, 0xff } },
|
||||
{ "orange", { 0xff, 0xa5, 0x00, 0xff } },
|
||||
|
||||
/* yellow */
|
||||
{ "yellow", { 0xff, 0xff, 0x00, 0xff } },
|
||||
{ "lightyellow", { 0xff, 0xff, 0xe0, 0xff } },
|
||||
{ "lemonchiffon", { 0xff, 0xfa, 0xcd, 0xff } },
|
||||
{ "lightgoldenrodyellow", { 0xfa, 0xfa, 0xd2, 0xff } },
|
||||
{ "papayawhip", { 0xff, 0xef, 0xd5, 0xff } },
|
||||
{ "moccasin", { 0xff, 0xe4, 0xb5, 0xff } },
|
||||
{ "peachpuff", { 0xff, 0xda, 0xb9, 0xff } },
|
||||
{ "palegoldenrod", { 0xee, 0xe8, 0xaa, 0xff } },
|
||||
{ "khaki", { 0xf0, 0xe6, 0x8c, 0xff } },
|
||||
{ "darkkhaki", { 0xbd, 0xb7, 0x6b, 0xff } },
|
||||
{ "gold", { 0xff, 0xd7, 0x00, 0xff } },
|
||||
|
||||
/* brown */
|
||||
{ "cornsilk", { 0xff, 0xf8, 0xdc, 0xff } },
|
||||
{ "blanchedalmond", { 0xff, 0xeb, 0xcd, 0xff } },
|
||||
{ "bisque", { 0xff, 0xe4, 0xc4, 0xff } },
|
||||
{ "navajowhite", { 0xff, 0xde, 0xad, 0xff } },
|
||||
{ "wheat", { 0xf5, 0xde, 0xb3, 0xff } },
|
||||
{ "burlywood", { 0xde, 0xb8, 0x87, 0xff } },
|
||||
{ "tan", { 0xd2, 0xb4, 0x8c, 0xff } },
|
||||
{ "rosybrown", { 0xbc, 0x8f, 0x8f, 0xff } },
|
||||
{ "sandybrown", { 0xf4, 0xa4, 0x60, 0xff } },
|
||||
{ "goldenrod", { 0xda, 0xa5, 0x20, 0xff } },
|
||||
{ "darkgoldenrod", { 0xb8, 0x86, 0x0b, 0xff } },
|
||||
{ "peru", { 0xcd, 0x85, 0x3f, 0xff } },
|
||||
{ "chocolate", { 0xd2, 0x69, 0x1e, 0xff } },
|
||||
{ "saddlebrown", { 0x8b, 0x45, 0x13, 0xff } },
|
||||
{ "sienna", { 0xa0, 0x52, 0x2d, 0xff } },
|
||||
{ "brown", { 0xa5, 0x2a, 0x2a, 0xff } },
|
||||
{ "maroon", { 0x80, 0x00, 0x00, 0xff } },
|
||||
|
||||
/* green */
|
||||
{ "darkolivegreen", { 0x55, 0x6b, 0x2f, 0xff } },
|
||||
{ "olive", { 0x80, 0x80, 0x00, 0xff } },
|
||||
{ "olivedrab", { 0x6b, 0x8e, 0x23, 0xff } },
|
||||
{ "yellowgreen", { 0x9a, 0xcd, 0x32, 0xff } },
|
||||
{ "limegreen", { 0x32, 0xcd, 0x32, 0xff } },
|
||||
{ "lime", { 0x00, 0xff, 0x00, 0xff } },
|
||||
{ "lawngreen", { 0x7c, 0xfc, 0x00, 0xff } },
|
||||
{ "chartreuse", { 0x7f, 0xff, 0x00, 0xff } },
|
||||
{ "greenyellow", { 0xad, 0xff, 0x2f, 0xff } },
|
||||
{ "springgreen", { 0x00, 0xff, 0x7f, 0xff } },
|
||||
{ "mediumspringgreen", { 0x00, 0xfa, 0x9a, 0xff } },
|
||||
{ "lightgreen", { 0x90, 0xee, 0x90, 0xff } },
|
||||
{ "palegreen", { 0x98, 0xfb, 0x98, 0xff } },
|
||||
{ "darkseagreen", { 0x8f, 0xbc, 0x8f, 0xff } },
|
||||
{ "mediumseagreen", { 0x3c, 0xb3, 0x71, 0xff } },
|
||||
{ "seagreen", { 0x2e, 0x8b, 0x57, 0xff } },
|
||||
{ "forestgreen", { 0x22, 0x8b, 0x22, 0xff } },
|
||||
{ "green", { 0x00, 0x80, 0x00, 0xff } },
|
||||
{ "darkgreen", { 0x00, 0x64, 0x00, 0xff } },
|
||||
|
||||
/* cyan */
|
||||
{ "mediumaquamarine", { 0x66, 0xcd, 0xaa, 0xff } },
|
||||
{ "aqua", { 0x00, 0xff, 0xff, 0xff } },
|
||||
{ "cyan", { 0x00, 0xff, 0xff, 0xff } },
|
||||
{ "lightcyan", { 0xe0, 0xff, 0xff, 0xff } },
|
||||
{ "paleturquoise", { 0xaf, 0xee, 0xee, 0xff } },
|
||||
{ "aquamarine", { 0x7f, 0xff, 0xd4, 0xff } },
|
||||
{ "turquoise", { 0x40, 0xe0, 0xd0, 0xff } },
|
||||
{ "mediumturquoise", { 0x48, 0xd1, 0xcc, 0xff } },
|
||||
{ "darkturquoise", { 0x00, 0xce, 0xd1, 0xff } },
|
||||
{ "lightseagreen", { 0x20, 0xb2, 0xaa, 0xff } },
|
||||
{ "cadetblue", { 0x5f, 0x9e, 0xa0, 0xff } },
|
||||
{ "darkcyan", { 0x00, 0x8b, 0x8b, 0xff } },
|
||||
{ "teal", { 0x00, 0x80, 0x80, 0xff } },
|
||||
|
||||
/* blue */
|
||||
{ "lightsteelblue", { 0xb0, 0xc4, 0xde, 0xff } },
|
||||
{ "powderblue", { 0xb0, 0xe0, 0xe6, 0xff } },
|
||||
{ "lightblue", { 0xad, 0xd8, 0xe6, 0xff } },
|
||||
{ "skyblue", { 0x87, 0xce, 0xeb, 0xff } },
|
||||
{ "lightskyblue", { 0x87, 0xce, 0xfa, 0xff } },
|
||||
{ "deepskyblue", { 0x00, 0xbf, 0xff, 0xff } },
|
||||
{ "dodgerblue", { 0x1e, 0x90, 0xff, 0xff } },
|
||||
{ "cornflowerblue", { 0x64, 0x95, 0xed, 0xff } },
|
||||
{ "steelblue", { 0x46, 0x82, 0xb4, 0xff } },
|
||||
{ "royalblue", { 0x41, 0x69, 0xe1, 0xff } },
|
||||
{ "blue", { 0x00, 0x00, 0xff, 0xff } },
|
||||
{ "mediumblue", { 0x00, 0x00, 0xcd, 0xff } },
|
||||
{ "darkblue", { 0x00, 0x00, 0x8b, 0xff } },
|
||||
{ "navy", { 0x00, 0x00, 0x80, 0xff } },
|
||||
{ "midnightblue", { 0x19, 0x19, 0x70, 0xff } },
|
||||
|
||||
/* purple */
|
||||
{ "lavender", { 0xe6, 0xe6, 0xfa, 0xff } },
|
||||
{ "thistle", { 0xd8, 0xbf, 0xd8, 0xff } },
|
||||
{ "plum", { 0xdd, 0xa0, 0xdd, 0xff } },
|
||||
{ "violet", { 0xee, 0x82, 0xee, 0xff } },
|
||||
{ "orchid", { 0xda, 0x70, 0xd6, 0xff } },
|
||||
{ "fuchsia", { 0xff, 0x00, 0xff, 0xff } },
|
||||
{ "magenta", { 0xff, 0x00, 0xff, 0xff } },
|
||||
{ "mediumorchid", { 0xba, 0x55, 0xd3, 0xff } },
|
||||
{ "mediumpurple", { 0x93, 0x70, 0xdb, 0xff } },
|
||||
{ "blueviolet", { 0x8a, 0x2b, 0xe2, 0xff } },
|
||||
{ "darkviolet", { 0x94, 0x00, 0xd3, 0xff } },
|
||||
{ "darkorchid", { 0x99, 0x32, 0xcc, 0xff } },
|
||||
{ "darkmagenta", { 0x8b, 0x00, 0x8b, 0xff } },
|
||||
{ "purple", { 0x80, 0x00, 0x80, 0xff } },
|
||||
{ "indigo", { 0x4b, 0x00, 0x82, 0xff } },
|
||||
{ "darkslateblue", { 0x48, 0x3d, 0x8b, 0xff } },
|
||||
{ "rebeccapurple", { 0x66, 0x33, 0x99, 0xff } },
|
||||
{ "slateblue", { 0x6a, 0x5a, 0xcd, 0xff } },
|
||||
{ "mediumslateblue", { 0x7b, 0x68, 0xee, 0xff } },
|
||||
|
||||
/* white */
|
||||
{ "white", { 0xff, 0xff, 0xff, 0xff } },
|
||||
{ "snow", { 0xff, 0xfa, 0xfa, 0xff } },
|
||||
{ "honeydew", { 0xf0, 0xff, 0xf0, 0xff } },
|
||||
{ "mintcream", { 0xf5, 0xff, 0xfa, 0xff } },
|
||||
{ "azure", { 0xf0, 0xff, 0xff, 0xff } },
|
||||
{ "aliceblue", { 0xf0, 0xf8, 0xff, 0xff } },
|
||||
{ "ghostwhite", { 0xf8, 0xf8, 0xff, 0xff } },
|
||||
{ "whitesmoke", { 0xf5, 0xf5, 0xf5, 0xff } },
|
||||
{ "seashell", { 0xff, 0xf5, 0xee, 0xff } },
|
||||
{ "beige", { 0xf5, 0xf5, 0xdc, 0xff } },
|
||||
{ "oldlace", { 0xfd, 0xf5, 0xe6, 0xff } },
|
||||
{ "floralwhite", { 0xff, 0xfa, 0xf0, 0xff } },
|
||||
{ "ivory", { 0xff, 0xff, 0xf0, 0xff } },
|
||||
{ "antiquewhite", { 0xfa, 0xeb, 0xd7, 0xff } },
|
||||
{ "linen", { 0xfa, 0xf0, 0xe6, 0xff } },
|
||||
{ "lavenderblush", { 0xff, 0xf0, 0xf5, 0xff } },
|
||||
{ "mistyrose", { 0xff, 0xe4, 0xe1, 0xff } },
|
||||
|
||||
/* grey/black */
|
||||
{ "gainsboro", { 0xdc, 0xdc, 0xdc, 0xff } },
|
||||
{ "lightgrey", { 0xd3, 0xd3, 0xd3, 0xff } },
|
||||
{ "silver", { 0xc0, 0xc0, 0xc0, 0xff } },
|
||||
{ "darkgray", { 0xa9, 0xa9, 0xa9, 0xff } },
|
||||
{ "gray", { 0x80, 0x80, 0x80, 0xff } },
|
||||
{ "dimgray", { 0x69, 0x69, 0x69, 0xff } },
|
||||
{ "lightslategray", { 0x77, 0x88, 0x99, 0xff } },
|
||||
{ "slategray", { 0x70, 0x80, 0x90, 0xff } },
|
||||
{ "darkslategray", { 0x2f, 0x4f, 0x4f, 0xff } },
|
||||
{ "black", { 0x00, 0x00, 0x00, 0xff } },
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
static colour<S,T>
|
||||
lookup_colour (const std::string &name,
|
||||
const std::map<std::string,colour<4,uint8_t>> &map)
|
||||
{
|
||||
std::string lower (name);
|
||||
std::transform (lower.begin (), lower.end (), lower.begin (), tolower);
|
||||
|
||||
auto pos = map.find (lower);
|
||||
if (pos == map.end ())
|
||||
throw std::out_of_range (name);
|
||||
|
||||
static_assert (S <= 4, "cannot invent additional data");
|
||||
return pos->second.template redim<S> ().template cast<T> ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
colour<S,T>
|
||||
colour<S,T>::from_html (const std::string &name)
|
||||
{
|
||||
return lookup_colour<S,T> (name, HTML_COLOURS);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
colour<S,T>
|
||||
colour<S,T>::from_x11 (const std::string &name)
|
||||
{
|
||||
return lookup_colour<S,T> (name, X11_COLOURS);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
colour3f
|
||||
util::rgb_to_hsv (colour3f rgb)
|
||||
{
|
||||
// Calculate chroma
|
||||
auto M = max (rgb);
|
||||
auto m = min (rgb);
|
||||
auto C = M - m;
|
||||
|
||||
// Undefined for zero chroma
|
||||
if (almost_zero (C))
|
||||
return { -1.f, 0.f, M };
|
||||
|
||||
// Calculate hue
|
||||
float H = exactly_equal (rgb.r, M) ? (rgb.g - rgb.b) :
|
||||
exactly_equal (rgb.g, M) ? 2 + (rgb.b - rgb.r) :
|
||||
exactly_equal (rgb.b, M) ? 4 + (rgb.r - rgb.g) :
|
||||
0 ;
|
||||
|
||||
H /= C;
|
||||
H *= 60;
|
||||
|
||||
if (H < 0)
|
||||
H += 360;
|
||||
|
||||
// Calculate value
|
||||
auto V = M;
|
||||
|
||||
// Calculate saturation
|
||||
auto S = almost_zero (V) ? 0.f : C / V;
|
||||
|
||||
return { H, S, V };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
colour3f
|
||||
util::hsv_to_rgb (colour3f hsv)
|
||||
{
|
||||
CHECK_GE (hsv.h, 0);
|
||||
CHECK_LT (hsv.h, 360);
|
||||
CHECK_GE (hsv.s, 0);
|
||||
CHECK_LE (hsv.s, 1);
|
||||
CHECK_GE (hsv.v, 0);
|
||||
CHECK_LE (hsv.v, 1);
|
||||
|
||||
float C = hsv.v * hsv.s;
|
||||
float H = hsv.h / 60;
|
||||
float X = C * (1 - std::abs (std::fmod (H, 2.f) - 1));
|
||||
|
||||
// monochromatic'ish
|
||||
if (almost_zero (hsv.s))
|
||||
return colour3f { hsv.v };
|
||||
|
||||
colour3f rgb;
|
||||
|
||||
unsigned hex = (unsigned)H;
|
||||
switch (hex) {
|
||||
case 0: rgb = { C, X, 0 }; break;
|
||||
case 1: rgb = { X, C, 0 }; break;
|
||||
case 2: rgb = { 0, C, X }; break;
|
||||
case 3: rgb = { 0, X, C }; break;
|
||||
case 4: rgb = { X, 0, C }; break;
|
||||
case 5: rgb = { C, 0, X }; break;
|
||||
}
|
||||
|
||||
auto m = hsv.v - C;
|
||||
|
||||
return rgb + m;
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Extract a colour object from a JSON node.
|
||||
#include "json/tree.hpp"
|
||||
|
||||
namespace json::tree {
|
||||
template <>
|
||||
util::colour4f
|
||||
io<util::colour4f>::deserialise (const node &root) {
|
||||
return {
|
||||
root[0].as<float> (),
|
||||
root[1].as<float> (),
|
||||
root[2].as<float> (),
|
||||
root[3].as<float> (),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
util::operator<< (std::ostream &os, util::colour<S,T> c)
|
||||
{
|
||||
return os << "[ " << util::make_infix (util::numeric_view (c), ", ") << ']';
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
std::istream&
|
||||
util::operator>> (std::istream &is, util::colour<S,T> &c)
|
||||
{
|
||||
std::array<
|
||||
std::conditional_t<
|
||||
sizeof(T) == 1,
|
||||
uint16_t,
|
||||
T
|
||||
>,S
|
||||
> v;
|
||||
|
||||
static_assert (S > 0, "current implementation requires strictly positive components");
|
||||
char comma;
|
||||
|
||||
for (size_t i = 0; i < S - 1; ++i) {
|
||||
is >> v[i] >> comma;
|
||||
|
||||
if (comma != ',' || is.eof ()) {
|
||||
is.setstate (std::ios_base::failbit);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
is >> v[S-1];
|
||||
|
||||
if (!std::is_same<T, typename decltype(v)::value_type>::value) {
|
||||
if (std::any_of (std::cbegin (v),
|
||||
std::cend (v),
|
||||
[] (auto i) {
|
||||
return i > std::numeric_limits<T>::max ();
|
||||
})) {
|
||||
is.setstate (std::ios_base::failbit);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
std::copy (std::cbegin (v),
|
||||
std::cend (v),
|
||||
std::begin (c));
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template std::istream& util::operator>> (std::istream&, util::colour<3,uint8_t>&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INSTANTIATE_S_T(S,T) \
|
||||
template \
|
||||
struct util::colour<S,T>; \
|
||||
\
|
||||
template \
|
||||
std::ostream& \
|
||||
util::operator<< (std::ostream&, util::colour<S,T>); \
|
||||
\
|
||||
template \
|
||||
const char* \
|
||||
util::to_string<util::colour<S,T>> (void);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#define INSTANTIATE_S(S) \
|
||||
INSTANTIATE_S_T(S,uint8_t) \
|
||||
INSTANTIATE_S_T(S,uint16_t) \
|
||||
INSTANTIATE_S_T(S,float) \
|
||||
INSTANTIATE_S_T(S,double)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
INSTANTIATE_S(1)
|
||||
INSTANTIATE_S(3)
|
||||
INSTANTIATE_S(4)
|
||||
return parse_hex (str);
|
||||
}
|
142
colour.hpp
142
colour.hpp
@ -11,7 +11,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_COLOUR_HPP
|
||||
@ -21,68 +21,98 @@
|
||||
#include "introspection.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace util {
|
||||
/// An RGBA colour POD type.
|
||||
template <size_t S, typename T>
|
||||
struct colour : public coord::base<S,T,colour,coord::rgba,coord::hsv> {
|
||||
using coord::base<S,T,util::colour,coord::rgba,coord::hsv>::base;
|
||||
using base_t = coord::base<S,T,util::colour,coord::rgba,coord::hsv>;
|
||||
/// An abstract colour POD type componsed of S components of type T.
|
||||
///
|
||||
/// Not to be used directly, instead the use of derived types is required.
|
||||
/// This exists purely to simplify generic colour code.
|
||||
template <
|
||||
size_t S,
|
||||
typename T,
|
||||
typename SelfT
|
||||
>
|
||||
struct colour : coord::base<S,T,SelfT> {
|
||||
using coord::base<S,T,SelfT>::base;
|
||||
|
||||
// overloaded cast operator which assumes values are unit normalised
|
||||
template <typename U>
|
||||
colour<S,U>
|
||||
cast (void) const;
|
||||
|
||||
/// parse colours specified as "#AABBCCDD".
|
||||
///
|
||||
/// * the leading hash is optional.
|
||||
/// * all components must be 2 hex digits.
|
||||
static colour parse_html (const char*);
|
||||
static colour parse_html (const std::string&);
|
||||
|
||||
/// look up the name of a colour from those specified in
|
||||
/// html/x11/etc specifications.
|
||||
static colour from_html (const std::string &name);
|
||||
static colour from_x11 (const std::string &name);
|
||||
|
||||
/// look up all the specifications and returns the colour from one
|
||||
/// that matches. the search order is unspecified, so if you want a
|
||||
/// known colour then try them first yourself.
|
||||
static colour from_string (const std::string &name);
|
||||
auto
|
||||
cast (void) const
|
||||
{
|
||||
::util::revalue_t<SelfT,U> ret;
|
||||
std::transform (std::begin (*this),
|
||||
std::end (*this),
|
||||
std::begin (ret),
|
||||
renormalise<T,U>);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
// Convenience types
|
||||
template <typename T> using colour1 = colour<1,T>;
|
||||
template <typename T> using colour3 = colour<3,T>;
|
||||
template <typename T> using colour4 = colour<4,T>;
|
||||
|
||||
typedef colour1<uint8_t> colour1u;
|
||||
typedef colour3<uint8_t> colour3u;
|
||||
typedef colour4<uint8_t> colour4u;
|
||||
|
||||
typedef colour1<float> colour1f;
|
||||
typedef colour3<float> colour3f;
|
||||
typedef colour4<float> colour4f;
|
||||
|
||||
// RGB/HSV conversions
|
||||
colour3f rgb_to_hsv (colour3f);
|
||||
colour3f hsv_to_rgb (colour3f);
|
||||
|
||||
// ostream/istream operators
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
operator<< (std::ostream&, util::colour<S,T>);
|
||||
|
||||
template <size_t S, typename T>
|
||||
std::istream&
|
||||
operator>> (std::istream&, util::colour<S,T>&);
|
||||
|
||||
// type name introspection specialisation
|
||||
template <size_t S, typename T>
|
||||
struct type_name<colour<S,T>> {
|
||||
static constexpr const char value[] = "colour";
|
||||
template <typename T>
|
||||
struct util::coord::store<1,T,srgba<1,T>> {
|
||||
union { struct { T r; }; T data[1]; };
|
||||
};
|
||||
template <typename T>
|
||||
struct util::coord::store<2,T,srgba<2,T>> {
|
||||
union { struct { T r, g; }; T data[2]; };
|
||||
};
|
||||
template <typename T>
|
||||
struct util::coord::store<3,T,srgba<3,T>> {
|
||||
union { struct { T r, g, b; }; T data[3]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<4,T,srgba<4,T>> {
|
||||
union { struct { T r, g, b, a; }; T data[4]; };
|
||||
};
|
||||
|
||||
template <size_t S, typename T> struct srgba : colour<S,T,srgba<S,T>> {
|
||||
using colour<S,T,srgba<S,T>>::colour;
|
||||
};
|
||||
|
||||
using srgba3f = srgba<3,float>;
|
||||
using srgba4f = srgba<4,float>;
|
||||
|
||||
using srgba3u = srgba<3,uint8_t>;
|
||||
using srgba4u = srgba<4,uint8_t>;
|
||||
|
||||
template <size_t S, typename T> struct hsva : colour<S,T,hsva<S,T>> {};
|
||||
|
||||
template <size_t S, typename T>
|
||||
struct redim_type<
|
||||
srgba<S,T>
|
||||
> { template <size_t _S> using type = srgba<_S,T>; };
|
||||
|
||||
template <size_t S, typename T>
|
||||
struct revalue_type<srgba<S,T>> {
|
||||
template <typename _T>
|
||||
using type = srgba<S,_T>;
|
||||
};
|
||||
|
||||
|
||||
template <typename> struct is_colour : public std::false_type {};
|
||||
template <
|
||||
size_t S,
|
||||
typename T,
|
||||
template <
|
||||
size_t,
|
||||
typename
|
||||
> typename ColourT
|
||||
> struct is_colour<ColourT<S,T>>
|
||||
:std::conditional_t<
|
||||
std::is_base_of_v<
|
||||
colour<S,T,ColourT<S,T>>,
|
||||
ColourT<S,T>
|
||||
>,
|
||||
std::true_type,
|
||||
std::false_type
|
||||
> {};
|
||||
|
||||
|
||||
template <typename T>
|
||||
constexpr auto is_colour_v = is_colour<T>::value;
|
||||
}
|
||||
|
||||
#include "colour.ipp"
|
||||
|
12
colour.ipp
12
colour.ipp
@ -19,15 +19,3 @@
|
||||
#endif
|
||||
#define __UTIL_COLOUR_IPP
|
||||
|
||||
template <size_t S, typename T>
|
||||
template <typename U>
|
||||
util::colour<S,U>
|
||||
util::colour<S,T>::cast (void) const
|
||||
{
|
||||
colour<S,U> ret;
|
||||
std::transform (this->begin (),
|
||||
this->end (),
|
||||
ret.begin (),
|
||||
renormalise<T,U>);
|
||||
return ret;
|
||||
}
|
||||
|
105
coord/base.hpp
105
coord/base.hpp
@ -17,36 +17,46 @@
|
||||
#ifndef CRUFT_UTIL_COORD_BASE_HPP
|
||||
#define CRUFT_UTIL_COORD_BASE_HPP
|
||||
|
||||
#include "init.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include "./ops.hpp"
|
||||
#include "ops.hpp"
|
||||
#include "init.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "../maths.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace util::coord {
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// the base class for all coordinate-like types.
|
||||
//
|
||||
// SelfT should not be exposed as a template template directly because
|
||||
// some types (eg, XYZ colours) do not conform to the same template
|
||||
// parameters are others (eg, vector2f). ie, it does not make sense to
|
||||
// allow redim, or type changing on some types so they just aren't exposed.
|
||||
template <
|
||||
std::size_t S,
|
||||
typename T,
|
||||
template <std::size_t, typename> class KLASS,
|
||||
typename ...tags
|
||||
typename SelfT
|
||||
>
|
||||
struct base : public init<S,T,tags...> {
|
||||
struct base : public init<S,T,SelfT> {
|
||||
static_assert (S > 0);
|
||||
static_assert (std::is_arithmetic<T>::value);
|
||||
static_assert (sizeof (init<S,T,SelfT>) == S * sizeof (T));
|
||||
|
||||
using self_t = SelfT;
|
||||
using value_type = T;
|
||||
static constexpr std::size_t dimension = S;
|
||||
static constexpr std::size_t elements = S;
|
||||
|
||||
/// returns the number of elements we contain
|
||||
static constexpr std::size_t size (void) { return S; }
|
||||
static constexpr auto size (void) { return S; }
|
||||
|
||||
// inherit the fancy elementwise constructors from `init'.
|
||||
using init<S,T,tags...>::init;
|
||||
// constructors
|
||||
using init<S,T,SelfT>::init;
|
||||
|
||||
/// constructs, but does not initialise, the data.
|
||||
///
|
||||
@ -63,12 +73,21 @@ namespace util::coord {
|
||||
this->data[i] = fill;
|
||||
}
|
||||
|
||||
constexpr base (const base<S,T,KLASS,tags...> &rhs) = default;
|
||||
base& operator= (const base<S,T,KLASS,tags...> &rhs) = default;
|
||||
constexpr base (const base<S,T,SelfT> &rhs) = default;
|
||||
base& operator= (const base<S,T,SelfT> &rhs)& = default;
|
||||
base& operator= (const T t)&
|
||||
{
|
||||
for (auto v: *this)
|
||||
v = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// element accessors
|
||||
T& operator[] (std::size_t i) { return this->data[i]; }
|
||||
constexpr const T& operator[] (std::size_t i) const { return this->data[i]; }
|
||||
constexpr T& operator[] (size_t i)& noexcept { return this->data[i]; }
|
||||
constexpr T& operator[] (int i)& noexcept { return this->data[i]; }
|
||||
|
||||
constexpr const T& operator[] (size_t i) const& noexcept { return this->data[i]; }
|
||||
constexpr const T& operator[] (int i) const& noexcept { return this->data[i]; }
|
||||
|
||||
auto cbegin (void) const { return std::cbegin (this->data); }
|
||||
auto cend (void) const { return std::cend (this->data); }
|
||||
@ -95,12 +114,28 @@ namespace util::coord {
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <
|
||||
typename K,
|
||||
typename = std::enable_if_t<is_coord_v<K>,void>
|
||||
>
|
||||
K as (void) const
|
||||
{
|
||||
static_assert (K::elements == elements);
|
||||
K k;
|
||||
std::copy (begin (), end (), k.begin ());
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------
|
||||
template <typename U>
|
||||
KLASS<S,U>
|
||||
auto
|
||||
cast (void) const
|
||||
{
|
||||
KLASS<S,U> out;
|
||||
typename revalue_type<SelfT>::template type<U> out;
|
||||
|
||||
std::copy (std::cbegin (this->data),
|
||||
std::cend (this->data),
|
||||
std::begin (out.data));
|
||||
@ -113,14 +148,21 @@ namespace util::coord {
|
||||
///
|
||||
/// explicitly does not allow a fill parameter given it can't be used
|
||||
/// when reducing dimensions.
|
||||
template <std::size_t D>
|
||||
template <
|
||||
size_t D,
|
||||
typename _sfinae = SelfT
|
||||
>
|
||||
std::enable_if_t<
|
||||
D <= S, KLASS<D,T>
|
||||
has_redim_v<_sfinae>,
|
||||
redim_t<_sfinae,D>
|
||||
>
|
||||
redim (void) const
|
||||
{
|
||||
KLASS<D,T> out;
|
||||
std::copy_n (cbegin (), D, std::begin (out.data));
|
||||
redim_t<SelfT,D> out;
|
||||
|
||||
std::copy_n (std::cbegin (this->data),
|
||||
min (S, D),
|
||||
std::begin (out.data));
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -132,13 +174,14 @@ namespace util::coord {
|
||||
///
|
||||
/// explicitly requires a fill parameter so that we avoid undefined
|
||||
/// values.
|
||||
template <std::size_t D>
|
||||
template<size_t D,typename _sfinae = SelfT>
|
||||
std::enable_if_t<
|
||||
(D > S), KLASS<D,T>
|
||||
has_redim_v<_sfinae>,
|
||||
redim_t<_sfinae,D>
|
||||
>
|
||||
redim (const KLASS<D,T> fill) const
|
||||
redim (const redim_t<_sfinae,D> fill) const
|
||||
{
|
||||
KLASS<D,T> out;
|
||||
redim_t<SelfT,D> out;
|
||||
|
||||
auto next = std::copy (cbegin (), cend (), std::begin (out));
|
||||
std::copy (std::cbegin (fill) + S, std::cend (fill), next);
|
||||
@ -151,13 +194,17 @@ namespace util::coord {
|
||||
///
|
||||
/// explicitly requires a fill parameter so that we avoid undefined
|
||||
/// values.
|
||||
template <std::size_t D>
|
||||
template <
|
||||
size_t D,
|
||||
typename _sfinae = SelfT
|
||||
>
|
||||
std::enable_if_t<
|
||||
(D > S), KLASS<D,T>
|
||||
has_redim_v<_sfinae>,
|
||||
redim_t<_sfinae,D>
|
||||
>
|
||||
redim (T fill) const
|
||||
{
|
||||
KLASS<D,T> out;
|
||||
redim_t<SelfT,D> out;
|
||||
|
||||
auto next = std::copy (cbegin (), cend (), std::begin (out));
|
||||
std::fill (next, std::end (out), fill);
|
||||
@ -172,7 +219,7 @@ namespace util::coord {
|
||||
/// it's ugly as sin, but simplifies some situations where we don't
|
||||
/// want a temporary.
|
||||
template <std::size_t ...Indices>
|
||||
KLASS<sizeof...(Indices),T>
|
||||
constexpr auto
|
||||
indices (void) const
|
||||
{
|
||||
static_assert (
|
||||
@ -180,11 +227,11 @@ namespace util::coord {
|
||||
"indices must fall within the defined range for the type"
|
||||
);
|
||||
|
||||
return KLASS<sizeof...(Indices),T> { this->data[Indices]... };
|
||||
return redim_t<SelfT,sizeof...(Indices)> {
|
||||
this->data[Indices]...
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include "../vector.hpp"
|
||||
|
||||
#endif
|
||||
|
@ -20,10 +20,17 @@
|
||||
#include <cstddef>
|
||||
|
||||
namespace util {
|
||||
template <std::size_t,typename> struct colour;
|
||||
template <std::size_t,typename> struct extent;
|
||||
template <std::size_t,typename> struct point;
|
||||
template <std::size_t,typename> struct vector;
|
||||
namespace coord {
|
||||
template <size_t S,typename T,typename ParentT> struct store;
|
||||
template <size_t,typename,typename> struct init;
|
||||
template <size_t,typename,typename> struct base;
|
||||
}
|
||||
|
||||
template <size_t,typename> struct srgba;
|
||||
template <size_t,typename> struct hsva;
|
||||
template <size_t,typename> struct extent;
|
||||
template <size_t,typename> struct point;
|
||||
template <size_t,typename> struct vector;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,53 +22,53 @@
|
||||
#include <cstddef>
|
||||
|
||||
namespace util::coord {
|
||||
template <std::size_t S, typename T, typename...>
|
||||
template <size_t S, typename T, typename SelfT>
|
||||
struct init;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct init<1,T,tags...> : public store<1,T,tags...>
|
||||
template <typename T, typename SelfT>
|
||||
struct init<1,T,SelfT> : public store<1,T,SelfT>
|
||||
{
|
||||
using store<1,T,tags...>::store;
|
||||
using store<1,T,SelfT>::store;
|
||||
constexpr init () = default;
|
||||
constexpr explicit init (T v0):
|
||||
store<1,T,tags...> ({v0})
|
||||
constexpr init (T v0):
|
||||
store<1,T,SelfT> ({v0})
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct init<2,T,tags...> : public store<2,T,tags...>
|
||||
template <typename T, typename SelfT>
|
||||
struct init<2,T,SelfT> : public store<2,T,SelfT>
|
||||
{
|
||||
using store<2,T,tags...>::store;
|
||||
using store<2,T,SelfT>::store;
|
||||
constexpr init () = default;
|
||||
constexpr init (T v0, T v1):
|
||||
store<2,T,tags...> ({ v0, v1 })
|
||||
store<2,T,SelfT> ({ v0, v1 })
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct init<3,T,tags...> : public store<3,T,tags...>
|
||||
template <typename T, typename SelfT>
|
||||
struct init<3,T,SelfT> : public store<3,T,SelfT>
|
||||
{
|
||||
using store<3,T,tags...>::store;
|
||||
using store<3,T,SelfT>::store;
|
||||
constexpr init () = default;
|
||||
constexpr init (T v0, T v1, T v2):
|
||||
store<3,T,tags...> ({v0, v1, v2})
|
||||
store<3,T,SelfT> ({v0, v1, v2})
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct init<4,T,tags...> : public store<4,T,tags...>
|
||||
template <typename T, typename SelfT>
|
||||
struct init<4,T,SelfT> : public store<4,T,SelfT>
|
||||
{
|
||||
using store<4,T,tags...>::store;
|
||||
using store<4,T,SelfT>::store;
|
||||
constexpr init () = default;
|
||||
constexpr init (T v0, T v1, T v2, T v3):
|
||||
store<4,T,tags...> ({ v0, v1, v2, v3 })
|
||||
store<4,T,SelfT> ({ v0, v1, v2, v3 })
|
||||
{ ; }
|
||||
};
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#ifndef CRUFT_UTIL_IOSTREAM
|
||||
#define CRUFT_UTIL_IOSTREAM
|
||||
|
||||
#include "./traits.hpp"
|
||||
#include "../iterator.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
@ -25,17 +26,16 @@
|
||||
|
||||
namespace util {
|
||||
template <
|
||||
template <std::size_t,typename> class K,
|
||||
std::size_t S,
|
||||
typename T
|
||||
typename K,
|
||||
typename = std::enable_if_t<is_coord_v<K>,void>
|
||||
>
|
||||
std::ostream&
|
||||
operator<< (std::ostream &os, const K<S,T> &k)
|
||||
operator<< (std::ostream &os, const K &k)
|
||||
{
|
||||
os << "[";
|
||||
std::transform (std::cbegin (k),
|
||||
std::cend (k),
|
||||
infix_iterator<T> (os, ", "),
|
||||
infix_iterator<typename K::value_type> (os, ", "),
|
||||
[] (auto i) { return +i; });
|
||||
os << "]";
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef CRUFT_UTIL_COORD_NAMES_HPP
|
||||
#define CRUFT_UTIL_COORD_NAMES_HPP
|
||||
|
||||
namespace util::coord {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// tags for accessor names
|
||||
//
|
||||
// colours
|
||||
struct rgba { };
|
||||
struct hsv { };
|
||||
|
||||
// physical positions
|
||||
struct xyzw { };
|
||||
|
||||
// texture coords
|
||||
struct stpq { };
|
||||
|
||||
// physical dimensions
|
||||
struct whd { };
|
||||
|
||||
// quaternions
|
||||
struct wxyz { };
|
||||
struct abcd { };
|
||||
}
|
||||
|
||||
#endif
|
1163
coord/ops.hpp
1163
coord/ops.hpp
File diff suppressed because it is too large
Load Diff
261
coord/store.hpp
261
coord/store.hpp
@ -17,11 +17,12 @@
|
||||
#ifndef CRUFT_UTIL_COORD_STORE_HPP
|
||||
#define CRUFT_UTIL_COORD_STORE_HPP
|
||||
|
||||
#include "names.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include "../preprocessor.hpp"
|
||||
#include "../platform.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
@ -55,156 +56,112 @@ namespace util::coord::detail {
|
||||
#define SIMD_ALIGN(S,T) alignas (util::coord::detail::alignment<T> (S))
|
||||
|
||||
|
||||
namespace util::coord {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Coordinate storage class.
|
||||
//
|
||||
// Types with trivially suitable arity are aligned appropriately to take
|
||||
// advantage of native platform SIMD. eg, 4f types are aligned to 16 bytes
|
||||
// on SSE platforms.
|
||||
template <
|
||||
std::size_t S,
|
||||
typename T,
|
||||
typename...
|
||||
>
|
||||
struct
|
||||
SIMD_ALIGN(S,T)
|
||||
store {
|
||||
T data[S];
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct store<3,T,rgba,hsv> {
|
||||
union {
|
||||
T data[3];
|
||||
struct { T r,g,b; };
|
||||
struct { T h,s,v; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Align on 16 bytes if the data is at least 16 bytes long. Prevents tiny
|
||||
// types like colour4u requiring massive alignments, reduces internal
|
||||
// fragmentation.
|
||||
//
|
||||
// TODO: expand this for other instruction sets. maybe switch on type.
|
||||
template <typename T>
|
||||
struct
|
||||
SIMD_ALIGN(4,T)
|
||||
store<4,T,rgba,hsv> {
|
||||
union {
|
||||
T data[4];
|
||||
struct { T r,g,b,a; };
|
||||
struct { T h,s,v; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct store<2,T,xyzw> {
|
||||
union {
|
||||
T data[2];
|
||||
struct { T x,y; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct store<3,T,xyzw> {
|
||||
union {
|
||||
T data[3];
|
||||
struct { T x,y,z; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Align on 16 bytes if the data is at least 16 bytes long. Prevents tiny
|
||||
// types like colour4u requiring massive alignments, reduces internal
|
||||
// fragmentation.
|
||||
//
|
||||
// TODO: expand this for other instruction sets. maybe switch on type.
|
||||
template <typename T>
|
||||
struct
|
||||
SIMD_ALIGN(4,T)
|
||||
store<4,T,xyzw> {
|
||||
union {
|
||||
T data[4];
|
||||
struct { T x,y,z,w; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct store<2,T,xyzw,stpq> {
|
||||
union {
|
||||
T data[2];
|
||||
struct { T x,y; };
|
||||
struct { T s,t; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct store<3,T,xyzw,stpq> {
|
||||
union {
|
||||
T data[3];
|
||||
struct { T x,y,z; };
|
||||
struct { T s,t,p; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Align on 16 bytes if the data is at least 16 bytes long. Prevents tiny
|
||||
// types like colour4u requiring massive alignments, reduces internal
|
||||
// fragmentation.
|
||||
//
|
||||
// TODO: expand this for other instruction sets. maybe switch on type.
|
||||
template <typename T>
|
||||
struct
|
||||
SIMD_ALIGN(4,T)
|
||||
store<4,T,xyzw,stpq> {
|
||||
union {
|
||||
T data[4];
|
||||
struct { T x,y,z,w; };
|
||||
struct { T s,t,p,q; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct store<2,T,whd> {
|
||||
union {
|
||||
T data[2];
|
||||
struct { T w,h; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct store<3,T,whd> {
|
||||
union {
|
||||
T data[3];
|
||||
struct { T w,h,d; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct
|
||||
SIMD_ALIGN(4,T)
|
||||
store<4,T,wxyz,abcd> {
|
||||
union {
|
||||
T data[4];
|
||||
struct { T w,x,y,z; };
|
||||
struct { T a,b,c,d; };
|
||||
};
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// defines the named member variables that a coordinate type is composed of
|
||||
#define DEFINE_COORD_STORE(TAG,...) \
|
||||
namespace util::coord { \
|
||||
template <typename T> \
|
||||
struct store< \
|
||||
VA_ARGS_COUNT(__VA_ARGS__), \
|
||||
T, \
|
||||
TAG \
|
||||
> { \
|
||||
union { \
|
||||
struct { \
|
||||
T __VA_ARGS__; \
|
||||
}; \
|
||||
T data[VA_ARGS_COUNT(__VA_ARGS__)]; \
|
||||
}; \
|
||||
}; \
|
||||
}
|
||||
|
||||
|
||||
#define DEFINE_STORE(KLASS,...) \
|
||||
template <typename T> \
|
||||
struct util::coord::store< \
|
||||
VA_ARGS_COUNT(__VA_ARGS__), \
|
||||
T, \
|
||||
::util::KLASS< \
|
||||
VA_ARGS_COUNT(__VA_ARGS__), \
|
||||
T \
|
||||
> \
|
||||
> { \
|
||||
union { \
|
||||
T data[VA_ARGS_COUNT(__VA_ARGS__)]; \
|
||||
struct { T __VA_ARGS__; }; \
|
||||
}; \
|
||||
};
|
||||
|
||||
DEFINE_STORE(extent,w)
|
||||
DEFINE_STORE(extent,w,h)
|
||||
DEFINE_STORE(extent,w,h,d)
|
||||
|
||||
DEFINE_STORE(point, x)
|
||||
DEFINE_STORE(point, x, y)
|
||||
DEFINE_STORE(point, x, y, z)
|
||||
DEFINE_STORE(point, x, y, z, w)
|
||||
|
||||
DEFINE_STORE(vector, x)
|
||||
DEFINE_STORE(vector, x, y)
|
||||
DEFINE_STORE(vector, x, y, z)
|
||||
DEFINE_STORE(vector, x, y, z, w)
|
||||
|
||||
#undef DEFINE_STORE
|
||||
|
||||
#if 0
|
||||
template <typename T>
|
||||
struct util::coord::store<1,T,::util::extent<1,T>> {
|
||||
union { T data[1]; struct { T w; }; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<2,T,::util::extent<2,T>> {
|
||||
union { struct { T w, h; }; T data[2]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<3,T,::util::extent<3,T>> {
|
||||
union { struct { T w, h, d; }; T data[3]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<1,T,::util::point<1,T>> {
|
||||
union { struct { T x; }; T data[1]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<2,T,::util::point<2,T>> {
|
||||
union { struct { T x, y; }; T data[2]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<3,T,::util::point<3,T>> {
|
||||
union { struct { T x, y, z; }; T data[3]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<4,T,::util::point<4,T>> {
|
||||
union { struct { T x, y, z, w; }; T data[4]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<1,T,::util::vector<1,T>> {
|
||||
union { struct { T x; }; T data[1]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<2,T,::util::vector<2,T>> {
|
||||
union { struct { T x, y; }; T data[2]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<3,T,::util::vector<3,T>> {
|
||||
union { struct { T x, y, z; }; T data[3]; };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct util::coord::store<4,T,::util::vector<4,T>> {
|
||||
union { struct { T x, y, z, w; }; T data[4]; };
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
225
coord/traits.hpp
Normal file
225
coord/traits.hpp
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2012-2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef CRUFT_UTIL_COORD_TRAITS_HPP
|
||||
#define CRUFT_UTIL_COORD_TRAITS_HPP
|
||||
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// operation traits
|
||||
template <typename, typename>
|
||||
struct result { };
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#define RESULT_T(ArgA,ArgB,ResultT) \
|
||||
template < \
|
||||
std::size_t S, \
|
||||
typename ValueA,\
|
||||
typename ValueB\
|
||||
> struct result<\
|
||||
ArgA<S,ValueA>,\
|
||||
ArgB<S,ValueB>\
|
||||
> {\
|
||||
using type = ResultT<S,std::common_type_t<ValueA,ValueB>>; \
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <
|
||||
std::size_t S,
|
||||
typename ValueA,
|
||||
typename ValueB
|
||||
> struct result<
|
||||
srgba<S,ValueA>,
|
||||
srgba<S,ValueB>
|
||||
> {
|
||||
using type = srgba<S,std::common_type_t<ValueA,ValueB>>;
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t S, typename T> struct result<srgba<S,T>, vector<S,T>> { using type = srgba<S,T>; };
|
||||
template <std::size_t S, typename T> struct result<vector<S,T>,srgba<S,T>> { using type = srgba<S,T>; };
|
||||
template <std::size_t S, typename T> struct result<extent<S,T>,extent<S,T>> { using type = extent<S,T>; };
|
||||
template <std::size_t S, typename T> struct result<extent<S,T>,vector<S,T>> { using type = extent<S,T>; };
|
||||
template <std::size_t S, typename T> struct result<point<S,T>, extent<S,T>> { using type = point <S,T>; };
|
||||
template <std::size_t S, typename T> struct result<point<S,T>, vector<S,T>> { using type = point <S,T>; };
|
||||
template <std::size_t S, typename T> struct result<vector<S,T>,point<S,T>> { using type = point <S,T>; };
|
||||
template <std::size_t S, typename T> struct result<vector<S,T>,vector<S,T>> { using type = vector<S,T>; };
|
||||
#endif
|
||||
|
||||
RESULT_T(extent,extent,extent)
|
||||
RESULT_T(extent,vector,extent)
|
||||
RESULT_T(point,extent,point)
|
||||
RESULT_T(point,vector,point)
|
||||
RESULT_T(srgba,vector,srgba)
|
||||
RESULT_T(srgba,srgba,srgba)
|
||||
RESULT_T(vector,point,point)
|
||||
RESULT_T(vector,srgba,srgba)
|
||||
RESULT_T(vector,vector,vector)
|
||||
|
||||
|
||||
template <
|
||||
typename A, typename B
|
||||
>
|
||||
using result_t = typename result<A,B>::type;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename A, typename B, typename = std::void_t<>>
|
||||
struct has_result : public std::false_type {};
|
||||
|
||||
|
||||
template <typename CoordA, typename CoordB>
|
||||
struct has_result<
|
||||
CoordA,
|
||||
CoordB,
|
||||
std::void_t<
|
||||
result_t<CoordA,CoordB>
|
||||
>
|
||||
> : public std::true_type {};
|
||||
|
||||
|
||||
template <typename A, typename B>
|
||||
constexpr auto has_result_v = has_result<A,B>::value;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename>
|
||||
struct has_norm : public std::false_type { };
|
||||
|
||||
template <std::size_t S, typename T> struct has_norm<vector<S,T>> : public std::true_type { };
|
||||
|
||||
template <typename T>
|
||||
constexpr auto has_norm_v = has_norm<T>::value;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct has_scalar_op : public std::false_type { };
|
||||
|
||||
template <std::size_t S, typename T> struct has_scalar_op<srgba<S,T>> : public std::true_type { };
|
||||
template <std::size_t S, typename T> struct has_scalar_op<extent<S,T>> : public std::true_type { };
|
||||
template <std::size_t S, typename T> struct has_scalar_op<point<S,T>> : public std::true_type { };
|
||||
template <std::size_t S, typename T> struct has_scalar_op<vector<S,T>> : public std::true_type { };
|
||||
|
||||
template <typename T>
|
||||
constexpr auto has_scalar_op_v = has_scalar_op<T>::value;
|
||||
|
||||
|
||||
template <class> struct is_coord : std::false_type { };
|
||||
|
||||
template <typename T> struct is_coord<const T> : is_coord<T> {};
|
||||
template <typename T> struct is_coord<T&> : is_coord<T> {};
|
||||
|
||||
template <std::size_t S, typename T> struct is_coord<point<S,T>> : std::true_type { };
|
||||
template <std::size_t S, typename T> struct is_coord<extent<S,T>> : std::true_type { };
|
||||
template <std::size_t S, typename T> struct is_coord<vector<S,T>> : std::true_type { };
|
||||
template <std::size_t S, typename T> struct is_coord<srgba<S,T>> : std::true_type { };
|
||||
|
||||
template <class K>
|
||||
constexpr bool
|
||||
is_coord_v = is_coord<K>::value;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct has_redim : std::false_type {};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <std::size_t S, typename T> struct has_redim< point<S,T>> : public std::true_type {};
|
||||
template <std::size_t S, typename T> struct has_redim<vector<S,T>> : public std::true_type {};
|
||||
template <std::size_t S, typename T> struct has_redim<extent<S,T>> : public std::true_type {};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename T> constexpr auto has_redim_v = has_redim<T>::value;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename> struct redim_type {};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <std::size_t S, typename T> struct redim_type<point<S,T>>
|
||||
{ template <std::size_t _S> using type = point<_S,T>; };
|
||||
|
||||
template <std::size_t S, typename T> struct redim_type<vector<S,T>>
|
||||
{ template <std::size_t _S> using type = vector<_S,T>; };
|
||||
|
||||
template <std::size_t S, typename T> struct redim_type<extent<S,T>>
|
||||
{ template <std::size_t _S> using type = extent<_S,T>; };
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <
|
||||
typename Self,
|
||||
std::size_t S
|
||||
>
|
||||
using redim_t = typename redim_type<Self>::template type<S>;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename> struct revalue_type {};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <std::size_t S, typename T>
|
||||
struct revalue_type<point<S,T>> {
|
||||
template <typename _T> using type = point<S,_T>;
|
||||
};
|
||||
|
||||
template <std::size_t S, typename T>
|
||||
struct revalue_type<vector<S,T>> {
|
||||
template <typename _T> using type = vector<S,_T>;
|
||||
};
|
||||
|
||||
template <std::size_t S, typename T>
|
||||
struct revalue_type<extent<S,T>> {
|
||||
template <typename _T> using type = extent<S,_T>;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename Self, typename T>
|
||||
using revalue_t = typename revalue_type<Self>::template type<T>;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename,typename=void> struct arity {};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct arity<T,std::enable_if_t<std::is_arithmetic_v<T>,void>
|
||||
> :std::integral_constant<std::size_t, 1>
|
||||
{ };
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct arity<
|
||||
T,std::enable_if_t<is_coord_v<T>,void>
|
||||
> :std::integral_constant<std::size_t,T::elements>
|
||||
{ };
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
constexpr auto arity_v = arity<T>::value;
|
||||
}
|
||||
|
||||
#endif
|
@ -21,7 +21,7 @@
|
||||
// Software Encryption - Fourth International Workshop, Haifa, Israel,
|
||||
// Springer-Verlag, pp. 69-82, 1997
|
||||
|
||||
#include "./ice.hpp"
|
||||
#include "ice.hpp"
|
||||
|
||||
#include "../endian.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
55
debug.hpp
55
debug.hpp
@ -427,36 +427,72 @@ namespace util::debug {
|
||||
void init (void);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// returns true if an instance of type `T' appears to be in a valid state.
|
||||
//
|
||||
// written as a struct rather than a function so that behaviour may be
|
||||
// arbitrarily specialised. all users are free to specialise this struct
|
||||
// with an user types.
|
||||
//
|
||||
// all specialisations must be safe to call on arbitrary data without
|
||||
// exceptions or faults as this mechanism is used to control some
|
||||
// debugging paths which themselves are the configuration points for
|
||||
// throwing/logging/etc behaviour.
|
||||
template <typename T>
|
||||
struct validator {
|
||||
static bool is_valid (const T&);
|
||||
static bool is_valid (const T&) noexcept;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
bool is_valid (const T &t)
|
||||
{ return validator<T>::is_valid (t); }
|
||||
bool is_valid (const T &t) noexcept
|
||||
{
|
||||
return validator<T>::is_valid (t);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
template<size_t, typename...> class T,
|
||||
size_t S,
|
||||
typename ...Args
|
||||
>
|
||||
struct validator<T<S,Args...>> {
|
||||
static bool is_valid (const T<S,Args...>&);
|
||||
static bool is_valid (const T<S,Args...>&) noexcept;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
template<size_t,typename...> class T,
|
||||
size_t S,
|
||||
typename ...Args
|
||||
>
|
||||
bool is_valid (const T<S,Args...> &v)
|
||||
{ return validator<T<S,Args...>>::is_valid (v); }
|
||||
bool is_valid (const T<S,Args...> &v) noexcept
|
||||
{
|
||||
return validator<T<S,Args...>>::is_valid (v);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// forwarding validator from a pointer type to a reference type.
|
||||
//
|
||||
// null pointers are assumed to be invalid
|
||||
template <typename T>
|
||||
struct validator<T*> {
|
||||
static bool is_valid (const T *val) noexcept
|
||||
{
|
||||
return val && ::util::debug::is_valid (*val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// asserts that an instance of type `T' is in a valid state.
|
||||
//
|
||||
// behaviour will be controlled by NDEBUG and other assertion machinery and
|
||||
// so may be optimised out entirely in optimised builds.
|
||||
template <typename T>
|
||||
void sanity (const T &t)
|
||||
{
|
||||
@ -465,6 +501,7 @@ namespace util::debug {
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
template<typename...> class T,
|
||||
typename ...Args
|
||||
@ -477,14 +514,16 @@ namespace util::debug {
|
||||
}
|
||||
|
||||
|
||||
#include "./debug.ipp"
|
||||
|
||||
|
||||
#include "debug.ipp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
|
||||
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
||||
// after we define the CHECK_ macros so the preprocessor can resolve them.
|
||||
#include "./maths.hpp"
|
||||
#include "maths.hpp"
|
||||
|
||||
|
||||
#endif // __DEBUG_HPP
|
||||
|
@ -34,7 +34,7 @@ namespace util::debug::detail {
|
||||
template <typename ...Args, size_t N>
|
||||
void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
||||
{
|
||||
std::cerr << format::printf (fmt, args...) << ::debug::backtrace () << std::endl;
|
||||
std::cerr << ::util::format::printf (fmt, args...) << ::debug::backtrace () << std::endl;
|
||||
breakpoint ();
|
||||
abort ();
|
||||
}
|
||||
|
@ -15,16 +15,16 @@
|
||||
* 2011-2016, Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include "./log.hpp"
|
||||
#include "log.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "./platform.hpp"
|
||||
|
||||
#if defined(PLATFORM_FREEBSD)
|
||||
#define PTRACE_ATTACH PT_ATTACH
|
||||
|
@ -14,11 +14,12 @@
|
||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include "./except.hpp"
|
||||
#include "./log.hpp"
|
||||
#include "./except.hpp"
|
||||
#include "except.hpp"
|
||||
#include "log.hpp"
|
||||
#include "except.hpp"
|
||||
#include "win32/error.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
@ -49,7 +50,7 @@ prepare_debugger (void)
|
||||
{
|
||||
if (nullptr == LoadLibrary("exchndl.dll")) {
|
||||
auto code = GetLastError ();
|
||||
LOG_WARNING("Emergency debugger not loaded: %s", util::win32_error::code_string (code));
|
||||
LOG_WARNING("Emergency debugger not loaded: %s", util::win32::error::code_string (code));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,18 +11,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_TIME_IPP
|
||||
#define __UTIL_TIME_IPP
|
||||
#include "base.hpp"
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
util::sleep (std::chrono::duration<T,std::nano> dt)
|
||||
{
|
||||
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds> (dt);
|
||||
sleep (nano.count ());
|
||||
}
|
||||
|
||||
#endif
|
251
encode/base.hpp
Normal file
251
encode/base.hpp
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef CRUFT_UTIL_BASE64_HPP
|
||||
#define CRUFT_UTIL_BASE64_HPP
|
||||
|
||||
#include "../view.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
|
||||
namespace util::encode {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <int Size>
|
||||
struct alphabet {
|
||||
static const char enc[Size];
|
||||
static const uint8_t dec[256];
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
const char alphabet<64>::enc[64] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <>
|
||||
const uint8_t alphabet<64>::dec[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3E, 0, 0, 0, 0x3F,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0, 0, 0, 0, 0, 0,
|
||||
0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
||||
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0, 0, 0, 0, 0,
|
||||
0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
const char alphabet<32>::enc[32] {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'2', '3', '4', '5', '6', '7',
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <>
|
||||
const uint8_t alphabet<32>::dec[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
const char alphabet<16>::enc[16] {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
};
|
||||
|
||||
template <>
|
||||
const uint8_t alphabet<16>::dec[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0, 0, 0, 0, 0, 0,
|
||||
0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <int Size> constexpr auto enc_v = alphabet<Size>::enc;
|
||||
template <int Size> constexpr auto dec_v = alphabet<Size>::dec;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// rfc4648 base16, base32, and base64 encoding
|
||||
template <int Size>
|
||||
struct base {
|
||||
static constexpr auto symbol_bits = log2 (Size);
|
||||
static constexpr auto group_bits = std::lcm (symbol_bits, 8);
|
||||
static constexpr auto group_symbols = group_bits / symbol_bits;
|
||||
static constexpr auto group_bytes = group_bits / 8;
|
||||
|
||||
static constexpr uint_fast32_t mask = (1<<symbol_bits)-1;
|
||||
|
||||
|
||||
template <typename InputT, typename OutputT>
|
||||
static OutputT
|
||||
encode (OutputT dst, const util::view<InputT> src)
|
||||
{
|
||||
// convert whole groups of symbols while we have enough bytes remaining
|
||||
auto cursor = std::cbegin (src);
|
||||
for (size_t i = 0, last = std::size (src) / group_bytes; i != last; ++i) {
|
||||
auto tally = std::accumulate (
|
||||
cursor, cursor + group_bytes,
|
||||
uint_fast32_t {0},
|
||||
[] (auto a, auto b) { return a << 8 | b; }
|
||||
);
|
||||
|
||||
cursor += group_bytes;
|
||||
|
||||
for (int j = group_symbols - 1; j >= 0; --j)
|
||||
*dst++ = enc_v<Size>[tally >> (j * symbol_bits) & mask];
|
||||
}
|
||||
|
||||
// we don't need to pad the output so we can early exit
|
||||
if (cursor == std::cend (src))
|
||||
return dst;
|
||||
|
||||
// accumulate the remaining bits and pad to a multiple of the
|
||||
// output group length
|
||||
auto tally = std::accumulate (
|
||||
cursor,
|
||||
std::cend (src),
|
||||
uint_fast32_t {0},
|
||||
[] (auto a, auto b) { return a << 8 | b; }
|
||||
);
|
||||
|
||||
auto input_remain = std::cend (src) - cursor;
|
||||
tally <<= symbol_bits - input_remain * 8 % symbol_bits;
|
||||
|
||||
// write each of the remaining symbols
|
||||
auto output_remain = (input_remain * 8 + symbol_bits - 1) / symbol_bits;
|
||||
for (auto i = output_remain - 1; i >= 0; --i)
|
||||
*dst++ = enc_v<Size>[tally >> (i * symbol_bits) & mask];
|
||||
|
||||
// pad the output to the symbol group size with '=' characters
|
||||
auto fill = (group_bytes - input_remain) * 8 / symbol_bits;
|
||||
return std::fill_n (dst, fill, '=');
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename InputT, typename OutputT>
|
||||
static OutputT
|
||||
decode (OutputT dst, util::view<InputT> src)
|
||||
{
|
||||
if (src.empty ())
|
||||
return dst;
|
||||
|
||||
if (src.size () % group_symbols)
|
||||
throw std::invalid_argument ("base-encoded strings must be a proper multiple of symbols");
|
||||
|
||||
union {
|
||||
uint_fast32_t num;
|
||||
uint8_t bytes[group_bytes];
|
||||
};
|
||||
|
||||
const bool padded = src.end ()[-1] == '=';
|
||||
auto cursor = std::cbegin (src);
|
||||
for (size_t i = 0, last = std::size (src) / group_symbols - padded?1:0;
|
||||
i != last;
|
||||
++i)
|
||||
{
|
||||
num = std::accumulate (
|
||||
cursor, cursor + group_symbols,
|
||||
uint_fast32_t {0},
|
||||
[] (auto a, auto b) {
|
||||
return a << symbol_bits | dec_v<Size>[static_cast<unsigned>(b)];
|
||||
}
|
||||
);
|
||||
|
||||
cursor += group_symbols;
|
||||
|
||||
dst = std::copy (std::crbegin (bytes), std::crend (bytes), dst);
|
||||
}
|
||||
|
||||
if (cursor != std::end (src)) {
|
||||
auto last = std::find (cursor, std::cend (src), '=');
|
||||
num = std::accumulate (
|
||||
cursor, last,
|
||||
uint_fast32_t{0},
|
||||
[] (auto a, auto b) {
|
||||
return a << symbol_bits | dec_v<Size>[static_cast<unsigned> (b)];
|
||||
}
|
||||
);
|
||||
|
||||
auto symbols = last - cursor;
|
||||
auto bits = symbols * symbol_bits;
|
||||
auto shift = bits%8;
|
||||
num >>= shift;
|
||||
|
||||
for (auto i = bits / 8; i; )
|
||||
*dst++ = bytes[--i];
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
202
except.cpp
202
except.cpp
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2010 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./except.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./platform.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
using util::errno_error;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct an errno_error from a given error value. The error value MUST signal an error at
|
||||
/// construction time.
|
||||
errno_error::errno_error (int _code):
|
||||
runtime_error (strerror (_code)),
|
||||
m_code (_code)
|
||||
{
|
||||
CHECK_NEQ (_code, 0);
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Construct an errno_error from the current value of errno. errno MUST signal an error at
|
||||
/// construction time.
|
||||
errno_error::errno_error ():
|
||||
errno_error (last_code ())
|
||||
{
|
||||
CHECK_NEQ (m_code, 0);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
errno_error::last_code (void)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
errno_error::code (void) const
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Throw an errno_error exception if errno currently signals an error.
|
||||
void
|
||||
errno_error::try_code (void)
|
||||
{
|
||||
try_code (last_code ());
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Throw an errno_error exception if 'code' represents an error.
|
||||
void
|
||||
errno_error::try_code (int code)
|
||||
{
|
||||
if (__builtin_expect (code != 0, false))
|
||||
throw errno_error(code);
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
void
|
||||
errno_error::throw_code (void)
|
||||
{
|
||||
throw_code (last_code ());
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
void
|
||||
errno_error::throw_code (int code)
|
||||
{
|
||||
CHECK_NEQ (code, 0);
|
||||
throw errno_error (code);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(PLATFORM_WIN32)
|
||||
|
||||
using util::win32_error;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
win32_error::win32_error (DWORD _code):
|
||||
runtime_error (code_string (_code)),
|
||||
m_code (_code)
|
||||
{
|
||||
CHECK_NEQ (m_code, (DWORD)ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
win32_error::win32_error (void):
|
||||
win32_error (last_code ())
|
||||
{ ; }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DWORD
|
||||
win32_error::code (void) const
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
DWORD
|
||||
win32_error::last_code (void)
|
||||
{
|
||||
return GetLastError ();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
win32_error::try_code (void)
|
||||
{
|
||||
try_code (last_code ());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
win32_error::try_code (DWORD id)
|
||||
{
|
||||
if (__builtin_expect (id != ERROR_SUCCESS, false))
|
||||
throw_code (id);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
win32_error::throw_code (void)
|
||||
{
|
||||
throw_code (last_code ());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
win32_error::throw_code (DWORD code)
|
||||
{
|
||||
CHECK_NEQ (code, (DWORD)ERROR_SUCCESS);
|
||||
throw win32_error (code);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string
|
||||
win32_error::code_string (void)
|
||||
{
|
||||
return code_string (last_code ());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string
|
||||
win32_error::code_string (DWORD code)
|
||||
{
|
||||
char message[256];
|
||||
|
||||
auto res = FormatMessage (
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
code,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
message,
|
||||
std::size (message),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (res == 0) {
|
||||
win32_error::throw_code ();
|
||||
}
|
||||
|
||||
return std::string (message, message + res);
|
||||
}
|
||||
#endif
|
97
except.hpp
97
except.hpp
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2010 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __EXCEPT_HPP
|
||||
#define __EXCEPT_HPP
|
||||
|
||||
#include "platform.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace util {
|
||||
class input_error : public std::runtime_error {
|
||||
public:
|
||||
explicit input_error (const std::string &_what):
|
||||
runtime_error (_what)
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
class output_error : public std::runtime_error {
|
||||
public:
|
||||
explicit output_error (const std::string &_what):
|
||||
runtime_error (_what)
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
class unavailable_error : public std::runtime_error {
|
||||
public:
|
||||
explicit unavailable_error (const std::string &_what):
|
||||
runtime_error (_what)
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
/// An exception class used for reporting errors signalled by errno.
|
||||
class errno_error : public std::runtime_error {
|
||||
public:
|
||||
explicit errno_error (int code);
|
||||
errno_error ();
|
||||
|
||||
int code (void) const;
|
||||
static int last_code (void);
|
||||
|
||||
static void try_code (void);
|
||||
static void try_code (int code);
|
||||
|
||||
static void throw_code [[gnu::noreturn]] (void);
|
||||
static void throw_code [[gnu::noreturn]] (int code);
|
||||
|
||||
private:
|
||||
int m_code;
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
namespace util {
|
||||
class win32_error : public std::runtime_error {
|
||||
public:
|
||||
explicit win32_error (DWORD _code);
|
||||
win32_error ();
|
||||
|
||||
DWORD code (void) const;
|
||||
static DWORD last_code (void);
|
||||
|
||||
static void try_code (void);
|
||||
static void try_code (DWORD);
|
||||
|
||||
static void throw_code [[gnu::noreturn]] (void);
|
||||
static void throw_code [[gnu::noreturn]] (DWORD);
|
||||
|
||||
static std::string code_string (void);
|
||||
static std::string code_string (DWORD);
|
||||
|
||||
private:
|
||||
DWORD m_code;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -14,10 +14,10 @@
|
||||
* Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./exe.hpp"
|
||||
#include "exe.hpp"
|
||||
|
||||
#include "./except.hpp"
|
||||
#include "./cast.hpp"
|
||||
#include "cast.hpp"
|
||||
#include "posix/except.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <experimental/filesystem>
|
||||
@ -39,7 +39,7 @@ util::image_path (void)
|
||||
retry:
|
||||
const auto written = readlink (PROC_SELF, resolved.data (), resolved.size ());
|
||||
if (written < 0)
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
if (sign_cast<size_t> (written) == resolved.size ()) {
|
||||
resolved.resize (resolved.size () * 2);
|
||||
|
@ -14,9 +14,10 @@
|
||||
* Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./exe.hpp"
|
||||
#include "exe.hpp"
|
||||
|
||||
#include "except.hpp"
|
||||
#incldue "win32/except.hpp"
|
||||
|
||||
#include <experimental/filesystem>
|
||||
#include <vector>
|
||||
@ -32,7 +33,7 @@ util::image_path (void)
|
||||
retry:
|
||||
const auto written = GetModuleFileName (nullptr, resolved.data (), resolved.size ());
|
||||
if (written == 0)
|
||||
win32_error::throw_code ();
|
||||
win32::error::throw_code ();
|
||||
|
||||
if (written == resolved.size ()) {
|
||||
resolved.resize (resolved.size () * 2);
|
||||
|
12
extent.cpp
12
extent.cpp
@ -14,10 +14,10 @@
|
||||
* Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./extent.hpp"
|
||||
#include "extent.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./maths.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "maths.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
@ -187,9 +187,9 @@ namespace util::debug {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#define INSTANTIATE_S_T(S,T) \
|
||||
template struct util::extent<S,T>; \
|
||||
template bool util::debug::is_valid (const extent<S,T>&); \
|
||||
template struct util::debug::validator<extent<S,T>>;
|
||||
template struct ::util::extent<S,T>; \
|
||||
template bool ::util::debug::is_valid (const ::util::extent<S,T>&); \
|
||||
template struct ::util::debug::validator<::util::extent<S,T>>;
|
||||
|
||||
#define INSTANTIATE(T) \
|
||||
INSTANTIATE_S_T(1,T) \
|
||||
|
32
extent.hpp
32
extent.hpp
@ -17,22 +17,24 @@
|
||||
#ifndef __UTIL_EXTENT_HPP
|
||||
#define __UTIL_EXTENT_HPP
|
||||
|
||||
#include "coord/fwd.hpp"
|
||||
#include "coord/base.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace util {
|
||||
/**
|
||||
* A pure two-dimensional size, without positioning
|
||||
* A pure n-dimensional size, without positioning
|
||||
*/
|
||||
template <size_t S, typename T>
|
||||
struct extent : public coord::base<S,T,extent,coord::whd>
|
||||
struct extent : public ::util::coord::base<S,T,::util::extent<S,T>>
|
||||
{
|
||||
using coord::base<S,T,util::extent,coord::whd>::base;
|
||||
using ::util::coord::base<S,T,::util::extent<S,T>>::base;
|
||||
|
||||
extent () = default;
|
||||
explicit extent (vector<S,T>);
|
||||
explicit extent (::util::vector<S,T>);
|
||||
|
||||
constexpr T area (void) const;
|
||||
constexpr T diameter (void) const;
|
||||
@ -41,7 +43,6 @@ namespace util {
|
||||
constexpr
|
||||
U aspect (void) const;
|
||||
|
||||
|
||||
/// tests whether a point would lie within:
|
||||
/// region { origin, *this }, inclusive of borders.
|
||||
///
|
||||
@ -62,24 +63,27 @@ namespace util {
|
||||
return all (p >= T{0} && p < *this);
|
||||
}
|
||||
|
||||
|
||||
extent expanded (vector<S,T>) const;
|
||||
extent expanded (T) const;
|
||||
extent contracted (vector<S,T>) const;
|
||||
extent contracted (T) const;
|
||||
::util::extent<S,T> expanded (::util::vector<S,T>) const;
|
||||
::util::extent<S,T> expanded (T) const;
|
||||
::util::extent<S,T> contracted (::util::vector<S,T>) const;
|
||||
::util::extent<S,T> contracted (T) const;
|
||||
|
||||
bool empty (void) const;
|
||||
|
||||
static constexpr extent max (void);
|
||||
static constexpr extent min (void);
|
||||
static constexpr ::util::extent<S,T> max (void);
|
||||
static constexpr ::util::extent<S,T> min (void);
|
||||
};
|
||||
|
||||
template <size_t S, typename T>
|
||||
struct extent_range {
|
||||
public:
|
||||
struct iterator : public std::iterator<std::forward_iterator_tag, point<S,T>, size_t> {
|
||||
struct iterator : public std::iterator<
|
||||
std::forward_iterator_tag,
|
||||
::util::point<S,T>,
|
||||
size_t
|
||||
> {
|
||||
public:
|
||||
iterator (extent<S,T>, util::point<S,T>);
|
||||
iterator (::util::extent<S,T>, ::util::point<S,T>);
|
||||
|
||||
point<S,T> operator* () const;
|
||||
iterator& operator++ (void);
|
||||
|
@ -17,9 +17,9 @@
|
||||
#ifndef __UTIL_FIXED_HPP
|
||||
#define __UTIL_FIXED_HPP
|
||||
|
||||
#include "./types/bits.hpp"
|
||||
#include "./maths.hpp"
|
||||
#include "./endian.hpp"
|
||||
#include "types/bits.hpp"
|
||||
#include "maths.hpp"
|
||||
#include "endian.hpp"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
|
@ -1 +1 @@
|
||||
#include "./filesystem.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./filesystem.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
||||
#include "../../except.hpp"
|
||||
|
||||
|
10
format.hpp
10
format.hpp
@ -17,7 +17,6 @@
|
||||
#ifndef CRUFT_UTIL_FORMAT_HPP
|
||||
#define CRUFT_UTIL_FORMAT_HPP
|
||||
|
||||
#include "maths.hpp"
|
||||
#include "view.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
@ -413,7 +412,7 @@ namespace util::format {
|
||||
static std::ostream&
|
||||
write (std::ostream &os, specifier s, const std::nullptr_t &val)
|
||||
{
|
||||
if (s.type != type_t::POINTER)
|
||||
if (s.type != type_t::POINTER || s.type == type_t::USER)
|
||||
throw std::runtime_error ("expected pointer specifier");
|
||||
return value<const void*>::write (os, s, val);
|
||||
}
|
||||
@ -424,8 +423,9 @@ namespace util::format {
|
||||
struct value<const char[N]> {
|
||||
static std::ostream&
|
||||
write (std::ostream &os, specifier spec, const char (&val)[N]) {
|
||||
if (spec.type == type_t::STRING)
|
||||
if (spec.type == type_t::STRING || spec.type == type_t::USER)
|
||||
return value<util::view<const char*>>::write (os, spec, util::view<const char*> (val));
|
||||
throw std::runtime_error ("invalid data type");
|
||||
}
|
||||
};
|
||||
|
||||
@ -445,7 +445,7 @@ namespace util::format {
|
||||
write (std::ostream &os, specifier spec, char *val) {
|
||||
if (!val)
|
||||
return os << "(nil)";
|
||||
if (spec.type == type_t::STRING)
|
||||
if (spec.type == type_t::STRING || spec.type == type_t::USER)
|
||||
return value<util::view<const char*>>::write (os, spec, util::view<const char*> { val, val + strlen (val) });
|
||||
if (spec.type == type_t::POINTER)
|
||||
return value<const void*>::write (os, spec, val);
|
||||
@ -460,7 +460,7 @@ namespace util::format {
|
||||
write (std::ostream &os, specifier spec, const char *val) {
|
||||
if (!val)
|
||||
return os << "(nil)";
|
||||
if (spec.type == type_t::STRING)
|
||||
if (spec.type == type_t::STRING || spec.type == type_t::USER)
|
||||
return value<util::view<const char*>>::write (os, spec, util::view<const char*> { val, val + strlen (val) });
|
||||
if (spec.type == type_t::POINTER)
|
||||
return value<const void*>::write (os, spec, val);
|
||||
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "./aabb.hpp"
|
||||
#include "aabb.hpp"
|
||||
|
||||
#include "./iostream.hpp"
|
||||
#include "iostream.hpp"
|
||||
#include "../coord/iostream.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
||||
@ -61,52 +61,6 @@ aabb<S,T>::closest (const point<S,T> q) const
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
aabb<S,T>
|
||||
aabb<S,T>::expand (const vector<S,T> mag) const noexcept
|
||||
{
|
||||
CHECK (all (mag >= T{0}));
|
||||
|
||||
return { p0 - mag, p1 + mag };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
aabb<S,T>
|
||||
aabb<S,T>::expand (const T mag) const noexcept
|
||||
{
|
||||
CHECK_GE (mag, T{0});
|
||||
|
||||
return { p0 - mag, p1 + mag };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
aabb<S,T>
|
||||
aabb<S,T>::contract (const util::vector<S,T> mag) const noexcept
|
||||
{
|
||||
CHECK (all (mag >= T{0}));
|
||||
CHECK (all (2 * mag <= p1 - p0));
|
||||
|
||||
return { p0 + mag, p1 - mag };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
aabb<S,T>
|
||||
aabb<S,T>::contract (const T mag) const noexcept
|
||||
{
|
||||
CHECK_GE (mag, T{0});
|
||||
CHECK (all (2 * mag <= p1 - p0));
|
||||
|
||||
return { p0 + mag, p1 - mag };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
void
|
||||
|
@ -44,19 +44,13 @@ namespace util::geom {
|
||||
|
||||
point<S,T> closest (point<S,T>) const;
|
||||
|
||||
aabb<S,T> expand (util::vector<S,T>) const noexcept;
|
||||
aabb<S,T> expand (T) const noexcept;
|
||||
|
||||
aabb<S,T> contract (util::vector<S,T>) const noexcept;
|
||||
aabb<S,T> contract (T) const noexcept;
|
||||
|
||||
void cover (point<S,T>);
|
||||
|
||||
aabb<S,T> operator+ (vector<S,T>) const;
|
||||
aabb<S,T> operator- (vector<S,T>) const;
|
||||
|
||||
point<S,T> p0;
|
||||
point<S,T> p1;
|
||||
::util::point<S,T> p0;
|
||||
::util::point<S,T> p1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./iostream.hpp"
|
||||
#include "iostream.hpp"
|
||||
|
||||
#include "./sphere.hpp"
|
||||
#include "sphere.hpp"
|
||||
#include "../coord/iostream.hpp"
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef __UTIL_GEOM_IOSTREAM_HPP
|
||||
#define __UTIL_GEOM_IOSTREAM_HPP
|
||||
|
||||
#include "./fwd.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
|
@ -24,8 +24,7 @@ using util::geom::plane;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
plane<S,T>::plane (point<S,T> _p,
|
||||
vector<S,T> _n):
|
||||
plane<S,T>::plane (point<S,T> _p, vector<S,T> _n):
|
||||
p (_p),
|
||||
n (_n)
|
||||
{
|
||||
|
@ -23,11 +23,10 @@
|
||||
namespace util::geom {
|
||||
template <size_t S, typename T>
|
||||
struct plane {
|
||||
plane (util::point<S,T> p,
|
||||
util::vector<S,T> n);
|
||||
plane (util::point<S,T>, util::vector<S,T>);
|
||||
|
||||
util::point<S,T> p;
|
||||
util::vector<S,T> n;
|
||||
::util::point<S,T> p;
|
||||
::util::vector<S,T> n;
|
||||
};
|
||||
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./ray.hpp"
|
||||
#include "ray.hpp"
|
||||
|
||||
#include "./iostream.hpp"
|
||||
#include "./ops.hpp"
|
||||
#include "iostream.hpp"
|
||||
#include "ops.hpp"
|
||||
#include "../coord/iostream.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
* Copyright 2010-2014 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./adler.hpp"
|
||||
#include "adler.hpp"
|
||||
|
||||
#include "./fletcher.hpp"
|
||||
#include "fletcher.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
||||
static constexpr unsigned MODULUS = 65521;
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef __UTIL_HASH_ADLER_HPP
|
||||
#define __UTIL_HASH_ADLER_HPP
|
||||
|
||||
#include "./fletcher.hpp"
|
||||
#include "fletcher.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -48,9 +48,8 @@ bsdsum::update (const void *restrict data, size_t size) noexcept
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
bsdsum::update (
|
||||
const uint8_t *const restrict first,
|
||||
const uint8_t *const restrict last) noexcept
|
||||
bsdsum::update (const uint8_t *const restrict first,
|
||||
const uint8_t *const restrict last) noexcept
|
||||
{
|
||||
CHECK (first);
|
||||
CHECK (last);
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./crc.hpp"
|
||||
#include "crc.hpp"
|
||||
|
||||
#include "../bitwise.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "./fletcher.hpp"
|
||||
#include "fletcher.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
// directly, and are unlikely to change given their inherent
|
||||
// lightweight nature.
|
||||
|
||||
#include "./fasthash.hpp"
|
||||
#include "./fnv1a.hpp"
|
||||
#include "./murmur.hpp"
|
||||
#include "fasthash.hpp"
|
||||
#include "fnv1a.hpp"
|
||||
#include "murmur.hpp"
|
||||
|
||||
|
||||
// Forward declerations of class based hashes
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "./keccak.hpp"
|
||||
#include "keccak.hpp"
|
||||
|
||||
#include "../endian.hpp"
|
||||
#include "../maths.hpp"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#ifndef __UTIL_HASH_MURMUR_HPP
|
||||
#define __UTIL_HASH_MURMUR_HPP
|
||||
|
||||
#include "./murmur/murmur1.hpp"
|
||||
#include "./murmur/murmur2.hpp"
|
||||
#include "./murmur/murmur3.hpp"
|
||||
#include "murmur/murmur1.hpp"
|
||||
#include "murmur/murmur2.hpp"
|
||||
#include "murmur/murmur3.hpp"
|
||||
|
||||
#endif
|
||||
|
@ -31,7 +31,7 @@ namespace util::hash::murmur2 {
|
||||
uint64_t hash_64 (const void *restrict data, size_t len, uint64_t seed);
|
||||
}
|
||||
|
||||
#include "./murmur2.ipp"
|
||||
#include "murmur2.ipp"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* 2014, Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./ripemd.hpp"
|
||||
#include "ripemd.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
#include "../bitwise.hpp"
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./sha1.hpp"
|
||||
#include "sha1.hpp"
|
||||
|
||||
#include "../bitwise.hpp"
|
||||
#include "../debug.hpp"
|
||||
|
@ -14,4 +14,4 @@
|
||||
* Copyright 2016, Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./simple.hpp"
|
||||
#include "simple.hpp"
|
||||
|
@ -14,11 +14,11 @@
|
||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./xxhash.hpp"
|
||||
#include "xxhash.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./bitwise.hpp"
|
||||
#include "./endian.hpp"
|
||||
#include "../bitwise.hpp"
|
||||
#include "../debug.hpp"
|
||||
#include "../endian.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
#ifndef __UTIL_INTROSPECTION_HPP
|
||||
#define __UTIL_INTROSPECTION_HPP
|
||||
|
||||
#include "./preprocessor.hpp"
|
||||
#include "./variadic.hpp"
|
||||
#include "preprocessor.hpp"
|
||||
#include "variadic.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
31
io.cpp
31
io.cpp
@ -17,9 +17,9 @@
|
||||
#include "io.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "except.hpp"
|
||||
#include "cast.hpp"
|
||||
#include "format.hpp"
|
||||
#include "posix/except.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fcntl.h>
|
||||
@ -45,12 +45,9 @@ util::slurp (const std::experimental::filesystem::path &path)
|
||||
posix::fd out (path, O_RDONLY | O_BINARY);
|
||||
|
||||
// Calculate the total file size
|
||||
off_t size = lseek (out, 0, SEEK_END);
|
||||
if (size == (off_t)-1)
|
||||
throw errno_error();
|
||||
off_t size = posix::error::try_value (lseek (out, 0, SEEK_END));
|
||||
|
||||
if (lseek (out, 0, SEEK_SET) == (off_t)-1)
|
||||
throw errno_error ();
|
||||
posix::error::try_value (lseek (out, 0, SEEK_SET));
|
||||
|
||||
// Allocate a buffer, and keep reading until it's full.
|
||||
std::vector<T> buffer (size);
|
||||
@ -60,9 +57,10 @@ util::slurp (const std::experimental::filesystem::path &path)
|
||||
T *cursor = buffer.data ();
|
||||
|
||||
while (remaining) {
|
||||
ssize_t consumed = ::read (out, cursor, remaining);
|
||||
if (consumed == -1)
|
||||
throw errno_error();
|
||||
ssize_t consumed = posix::error::try_value(
|
||||
::read (out, cursor, remaining)
|
||||
);
|
||||
|
||||
CHECK_GT ( consumed, 0);
|
||||
CHECK_LE ((size_t)consumed, remaining);
|
||||
|
||||
@ -90,13 +88,10 @@ util::slurp (FILE *stream)
|
||||
);
|
||||
|
||||
// find how much data is in this file
|
||||
const int desc = fileno (stream);
|
||||
if (desc < 0)
|
||||
errno_error::throw_code ();
|
||||
const int desc = util::posix::error::try_value (fileno (stream));
|
||||
|
||||
struct stat meta;
|
||||
if (fstat (desc, &meta) < 0)
|
||||
errno_error::throw_code ();
|
||||
posix::error::try_value (fstat (desc, &meta));
|
||||
|
||||
std::vector<T> buf;
|
||||
|
||||
@ -145,9 +140,7 @@ util::write (const posix::fd &out,
|
||||
size_t remaining = bytes;
|
||||
|
||||
while (remaining) {
|
||||
ssize_t consumed = ::write (out, cursor, remaining);
|
||||
if (consumed < 0)
|
||||
errno_error::throw_code ();
|
||||
ssize_t consumed = posix::error::try_value (::write (out, cursor, remaining));
|
||||
|
||||
remaining -= sign_cast<size_t> (consumed);
|
||||
cursor += sign_cast<size_t> (consumed);
|
||||
@ -199,7 +192,7 @@ scoped_cwd::scoped_cwd ()
|
||||
m_original.resize (16);
|
||||
while (getcwd (&m_original[0], m_original.size ()) == nullptr && errno == ERANGE)
|
||||
m_original.resize (m_original.size () * 2);
|
||||
errno_error::try_code ();
|
||||
posix::error::try_code ();
|
||||
}
|
||||
|
||||
|
||||
@ -207,7 +200,7 @@ scoped_cwd::scoped_cwd ()
|
||||
scoped_cwd::~scoped_cwd ()
|
||||
{
|
||||
if (!chdir (m_original.c_str ()))
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
}
|
||||
|
||||
|
||||
|
50
io.hpp
50
io.hpp
@ -43,16 +43,48 @@ namespace util {
|
||||
std::vector<T> slurp (FILE *);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
void write (const posix::fd&, const void *restrict data, size_t bytes);
|
||||
|
||||
template <typename T>
|
||||
void write (const posix::fd&, const T &data);
|
||||
|
||||
template <typename T>
|
||||
void write (const posix::fd&, const T *restrict first, const T *restrict last);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline void
|
||||
write (const posix::fd &dst, util::view<const uint8_t*> data)
|
||||
{
|
||||
write (dst, std::data (data), std::size (data));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void write (const posix::fd &_fd, const T &data)
|
||||
{
|
||||
return write (_fd, make_view (data));
|
||||
}
|
||||
|
||||
|
||||
///------------------------------------------------------------------------
|
||||
/// writes all data from the provided view into the file-like-object
|
||||
///
|
||||
/// writing will continually iterate until the entire buffer has been
|
||||
/// dispatched so as to avoid issues with partial writes. will block until
|
||||
/// such time as the entire buffer has written.
|
||||
///
|
||||
/// an exception may be thrown in the event forward progress is impossible.
|
||||
/// in this event the progress may not be reported to the caller. in the
|
||||
/// future an exception member variable may expose the information.
|
||||
template <typename DstT, typename IteratorA, typename IteratorB>
|
||||
util::view<IteratorA,IteratorB>
|
||||
write (DstT &dst, const util::view<IteratorA, IteratorB> src)
|
||||
{
|
||||
auto remain = src;
|
||||
while (!remain.empty ())
|
||||
remain = src - dst.write (remain);
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class indenter : public std::streambuf {
|
||||
protected:
|
||||
std::streambuf* m_dest;
|
||||
@ -120,11 +152,11 @@ namespace util {
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include "./io_win32.hpp"
|
||||
#include "io_win32.hpp"
|
||||
#else
|
||||
#include "./io_posix.hpp"
|
||||
#include "io_posix.hpp"
|
||||
#endif
|
||||
|
||||
#include "./io.ipp"
|
||||
#include "io.ipp"
|
||||
|
||||
#endif
|
||||
|
9
io.ipp
9
io.ipp
@ -23,15 +23,6 @@
|
||||
#endif
|
||||
|
||||
namespace util {
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void
|
||||
write (const posix::fd &_fd, const T &data)
|
||||
{
|
||||
write (_fd, &data, sizeof (T));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
#include "io.hpp"
|
||||
|
||||
#include "cast.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "except.hpp"
|
||||
#include "posix/fd.hpp"
|
||||
#include "./cast.hpp"
|
||||
#include "posix/except.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -38,13 +38,12 @@ mapped_file::mapped_file (const std::experimental::filesystem::path &path,
|
||||
mapped_file::mapped_file (const ::util::posix::fd &src, int mflags)
|
||||
{
|
||||
struct stat meta;
|
||||
if (fstat (src, &meta) < 0)
|
||||
throw errno_error ();
|
||||
::util::posix::error::try_value (fstat (src, &meta));
|
||||
|
||||
m_size = sign_cast<size_t> (meta.st_size);
|
||||
m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, src, 0);
|
||||
if (m_data == MAP_FAILED)
|
||||
throw errno_error ();
|
||||
::util::posix::error::throw_code ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#define __UTIL_IO_POSIX_IPP
|
||||
|
||||
#include "./pointer.hpp"
|
||||
#include "pointer.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
13
io_win32.cpp
13
io_win32.cpp
@ -14,10 +14,11 @@
|
||||
* Copyright 2014 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./io_win32.hpp"
|
||||
#include "io_win32.hpp"
|
||||
|
||||
#include "./debug.hpp"
|
||||
#include "./except.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "except.hpp"
|
||||
#include "win32/error.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@ -94,11 +95,11 @@ mapped_file::mapped_file (::util::win32::handle &&src,
|
||||
// hell. Try not to collapse, but instead bail with a null mapping and
|
||||
// pray the user doesn't do something stupid with the result.
|
||||
if (!m_mapping) {
|
||||
auto err = win32_error::last_code ();
|
||||
auto err = win32::error::last_code ();
|
||||
if (err == ERROR_FILE_INVALID && m_size == 0)
|
||||
return;
|
||||
|
||||
win32_error::throw_code (err);
|
||||
win32::error::throw_code (err);
|
||||
}
|
||||
|
||||
auto view = MapViewOfFile (
|
||||
@ -109,7 +110,7 @@ mapped_file::mapped_file (::util::win32::handle &&src,
|
||||
);
|
||||
|
||||
if (!view)
|
||||
win32_error::throw_code ();
|
||||
win32::error::throw_code ();
|
||||
|
||||
m_data.reset (
|
||||
static_cast<unsigned char*> (view)
|
||||
|
@ -17,9 +17,9 @@
|
||||
#ifndef __UTIL_IO_WIN32_HPP
|
||||
#define __UTIL_IO_WIN32_HPP
|
||||
|
||||
#include "./io.hpp"
|
||||
#include "./win32/handle.hpp"
|
||||
#include "./view.hpp"
|
||||
#include "io.hpp"
|
||||
#include "win32/handle.hpp"
|
||||
#include "view.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <experimental/filesystem>
|
||||
|
78
iterator.hpp
78
iterator.hpp
@ -438,6 +438,84 @@ namespace util {
|
||||
discard_iterator operator++ (int) { return *this; }
|
||||
discard_iterator& operator* ( ) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// an iterator that can be infinitely incremented but never assigned.
|
||||
///
|
||||
/// useful for iterator ranges where the begin iterator is an output
|
||||
/// iterator and hence never reaches an end point (and where we don't want
|
||||
/// to engineer the client code to account for this).
|
||||
template <
|
||||
typename ValueT,
|
||||
typename CategoryT,
|
||||
typename DistanceT,
|
||||
typename PointerT,
|
||||
typename ReferenceT
|
||||
>
|
||||
struct unequal_iterator {
|
||||
using value_type = ValueT;
|
||||
using iterator_category = CategoryT;
|
||||
using difference_type = DistanceT;
|
||||
using pointer = PointerT;
|
||||
using reference = ReferenceT;
|
||||
|
||||
unequal_iterator& operator++ ( ) { return *this; }
|
||||
unequal_iterator operator++ (int) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename ContainerT>
|
||||
auto
|
||||
make_unequal_iterator (const ContainerT&)
|
||||
{
|
||||
using t = typename std::iterator_traits<typename ContainerT::iterator>;
|
||||
|
||||
return unequal_iterator<
|
||||
typename t::value_type,
|
||||
typename t::iterator_category,
|
||||
typename t::difference_type,
|
||||
typename t::pointer,
|
||||
typename t::reference
|
||||
> {};
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
typename OtherT,
|
||||
|
||||
typename ValueT,
|
||||
typename CategoryT,
|
||||
typename DistanceT,
|
||||
typename PointerT,
|
||||
typename ReferenceT>
|
||||
constexpr bool
|
||||
operator== (
|
||||
const unequal_iterator<ValueT,CategoryT,DistanceT,PointerT,ReferenceT>&,
|
||||
const OtherT&
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
typename OtherT,
|
||||
|
||||
typename ValueT,
|
||||
typename CategoryT,
|
||||
typename DistanceT,
|
||||
typename PointerT,
|
||||
typename ReferenceT>
|
||||
constexpr bool
|
||||
operator== (
|
||||
const OtherT&,
|
||||
const unequal_iterator<ValueT,CategoryT,DistanceT,PointerT,ReferenceT>&
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -14,10 +14,10 @@
|
||||
* Copyright 2015-2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./schema.hpp"
|
||||
#include "schema.hpp"
|
||||
|
||||
#include "./tree.hpp"
|
||||
#include "./except.hpp"
|
||||
#include "tree.hpp"
|
||||
#include "except.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
#include "../io.hpp"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef __UTIL_JSON_SCHEMA_HPP
|
||||
#define __UTIL_JSON_SCHEMA_HPP
|
||||
|
||||
#include "./fwd.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <experimental/filesystem>
|
||||
|
||||
|
@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "./tree.hpp"
|
||||
#include "tree.hpp"
|
||||
|
||||
#include "./except.hpp"
|
||||
#include "./flat.hpp"
|
||||
#include "except.hpp"
|
||||
#include "flat.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
#include "../io.hpp"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#ifndef __UTIL_JSON_TREE_HPP
|
||||
#define __UTIL_JSON_TREE_HPP
|
||||
|
||||
#include "./flat.hpp"
|
||||
#include "./fwd.hpp"
|
||||
#include "flat.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include "../iterator.hpp"
|
||||
#include "../view.hpp"
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "library_win32.hpp"
|
||||
|
||||
#include "except.hpp"
|
||||
#include "win32/except.hpp"
|
||||
|
||||
using util::detail::win32::library;
|
||||
|
||||
@ -26,7 +26,7 @@ library::library (const std::experimental::filesystem::path &path):
|
||||
m_handle (LoadLibraryA (path.c_str ()))
|
||||
{
|
||||
if (!m_handle)
|
||||
win32_error::throw_code ();
|
||||
win32::error::throw_code ();
|
||||
}
|
||||
|
||||
|
||||
|
21
maths.cpp
21
maths.cpp
@ -31,27 +31,6 @@ template uint32_t util::log2up (uint32_t);
|
||||
template uint64_t util::log2up (uint64_t);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
T
|
||||
util::log2 (T v)
|
||||
{
|
||||
static_assert (std::is_integral<T>::value,
|
||||
"log2 is only implemented for integers");
|
||||
|
||||
T l = 0;
|
||||
while (v >>= 1)
|
||||
++l;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
template uint8_t util::log2 (uint8_t);
|
||||
template uint16_t util::log2 (uint16_t);
|
||||
template uint32_t util::log2 (uint32_t);
|
||||
template uint64_t util::log2 (uint64_t);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template const float util::PI<float>;
|
||||
template const double util::PI<double>;
|
||||
|
79
maths.hpp
79
maths.hpp
@ -21,8 +21,8 @@
|
||||
// it triggers a circular dependency; debug -> format -> maths -> debug
|
||||
// instead, just use cassert
|
||||
|
||||
#include "./types/traits.hpp"
|
||||
#include "./float.hpp"
|
||||
#include "types/traits.hpp"
|
||||
#include "float.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -81,8 +81,8 @@ namespace util {
|
||||
template <typename A, typename B>
|
||||
inline
|
||||
typename std::enable_if_t<
|
||||
std::is_integral<A>::value &&
|
||||
std::is_integral<B>::value &&
|
||||
std::is_integral_v<A> &&
|
||||
std::is_integral_v<B> &&
|
||||
std::is_signed<A>::value == std::is_signed<B>::value,
|
||||
bool
|
||||
>
|
||||
@ -203,7 +203,7 @@ namespace util {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
T
|
||||
std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
abs [[gnu::const]] (T t)
|
||||
{
|
||||
return t > 0 ? t : -t;
|
||||
@ -221,11 +221,19 @@ namespace util {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
constexpr T
|
||||
pow [[gnu::const]] (T x, unsigned y)
|
||||
template <
|
||||
typename BaseT,
|
||||
typename ExponentT,
|
||||
typename = std::enable_if_t<
|
||||
std::is_unsigned_v<ExponentT>,
|
||||
void
|
||||
>
|
||||
>
|
||||
constexpr BaseT
|
||||
pow [[gnu::const]] (BaseT base, ExponentT exponent)
|
||||
{
|
||||
return y == 0 ? T{1} : x * pow (x, y - 1);
|
||||
assert (exponent >= 0);
|
||||
return exponent == 0 ? BaseT{1} : base * pow (base, exponent - 1);
|
||||
}
|
||||
|
||||
|
||||
@ -242,8 +250,15 @@ namespace util {
|
||||
//-----------------------------------------------------------------------------
|
||||
// Logarithms
|
||||
template <typename T>
|
||||
T
|
||||
log2 (T val);
|
||||
constexpr
|
||||
std::enable_if_t<std::is_integral_v<T>, T>
|
||||
log2 (T val)
|
||||
{
|
||||
T tally = 0;
|
||||
while (val >>= 1)
|
||||
++tally;
|
||||
return tally;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -326,11 +341,29 @@ namespace util {
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
constexpr
|
||||
unsigned
|
||||
digits10 (uint32_t v) noexcept
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
typename NumericT,
|
||||
typename = std::enable_if_t<
|
||||
std::is_integral_v<NumericT>,
|
||||
void
|
||||
>
|
||||
>
|
||||
constexpr auto
|
||||
digits10 (NumericT v) noexcept
|
||||
{
|
||||
// cascading conditionals are faster, but it's super annoying to write
|
||||
// out for arbitrarily sized types so we use this base case unti
|
||||
// there's actually a performance reason to use another algorithm.
|
||||
int tally = 0;
|
||||
do {
|
||||
v /= 10;
|
||||
++tally;
|
||||
} while (v);
|
||||
|
||||
return tally;
|
||||
|
||||
/*
|
||||
return (v >= 1000000000) ? 10 :
|
||||
(v >= 100000000) ? 9 :
|
||||
(v >= 10000000) ? 8 :
|
||||
@ -341,6 +374,7 @@ namespace util {
|
||||
(v >= 100) ? 3 :
|
||||
(v >= 10) ? 2 :
|
||||
1;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -587,7 +621,16 @@ namespace util {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// Variadic minimum
|
||||
template <typename T>
|
||||
|
||||
// disable the single parameter version for non-arithmetic types so that
|
||||
// min for coord types is unambiguous. allow pointers too because it
|
||||
// doesn't add ambiguity and it simplifies some memory juggling.
|
||||
template <
|
||||
typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_arithmetic_v<T> || std::is_pointer_v<T>, void
|
||||
>
|
||||
>
|
||||
constexpr T
|
||||
min (const T a)
|
||||
{ return a; }
|
||||
@ -609,9 +652,9 @@ namespace util {
|
||||
//-------------------------------------------------------------------------
|
||||
/// Variadic maximum
|
||||
template <typename T>
|
||||
constexpr T
|
||||
constexpr std::enable_if_t<std::is_arithmetic_v<T> || std::is_pointer_v<T>, T>
|
||||
max (const T a)
|
||||
{ return a; }
|
||||
{ return a; }
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
142
matrix.cpp
142
matrix.cpp
@ -27,7 +27,8 @@ using util::matrix;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//template <size_t S, typename T>
|
||||
//-----------------------------------------------------------------------------
|
||||
//template <std::size_t S, typename T>
|
||||
//matrix<S,T>&
|
||||
//matrix<S,T>::invert_affine (void)
|
||||
//{
|
||||
@ -76,7 +77,7 @@ using util::matrix;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
T
|
||||
util::matrix<Rows,Cols,T>::determinant (void) const
|
||||
{
|
||||
@ -85,7 +86,7 @@ util::matrix<Rows,Cols,T>::determinant (void) const
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
util::matrix<Rows,Cols,T>
|
||||
util::matrix<Rows,Cols,T>::inverse (void) const
|
||||
{
|
||||
@ -94,14 +95,14 @@ util::matrix<Rows,Cols,T>::inverse (void) const
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Cols,Rows,T>
|
||||
util::transposed (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
util::matrix<Cols,Rows,T> res;
|
||||
|
||||
for (size_t y = 0; y < Rows; ++y)
|
||||
for (size_t x = 0; x < Cols; ++x)
|
||||
for (std::size_t y = 0; y < Rows; ++y)
|
||||
for (std::size_t x = 0; x < Cols; ++x)
|
||||
res[y][x] = m[x][y];
|
||||
|
||||
return res;
|
||||
@ -114,42 +115,14 @@ template util::matrix4f util::transposed (const matrix4f&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
util::vector<Rows,T>
|
||||
matrix<Rows,Cols,T>::operator* (const vector<Rows,T> &rhs) const
|
||||
{
|
||||
vector<Rows,T> out;
|
||||
|
||||
for (size_t i = 0; i < Rows; ++i)
|
||||
out[i] = dot (rhs, values[i]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
util::point<Rows,T>
|
||||
matrix<Rows,Cols,T>::operator* (const point<Rows,T> &rhs) const
|
||||
{
|
||||
point<Rows,T> out;
|
||||
|
||||
for (size_t i = 0; i < Rows; ++i)
|
||||
out[i] = dot (rhs, values[i]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
bool
|
||||
matrix<Rows,Cols,T>::is_affine (void) const
|
||||
{
|
||||
if (Rows != Cols)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < Rows - 1; ++i)
|
||||
for (std::size_t i = 0; i < Rows - 1; ++i)
|
||||
if (!exactly_zero (values[Rows-1][i]))
|
||||
return false;
|
||||
|
||||
@ -158,11 +131,11 @@ matrix<Rows,Cols,T>::is_affine (void) const
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::ortho (T left, T right,
|
||||
T bottom, T top,
|
||||
T near, T far)
|
||||
util::ortho (T left, T right,
|
||||
T bottom, T top,
|
||||
T near, T far)
|
||||
{
|
||||
CHECK_GT (far, near);
|
||||
|
||||
@ -174,29 +147,31 @@ matrix<Rows,Cols,T>::ortho (T left, T right,
|
||||
T tb = 2 / (top - bottom);
|
||||
T fn = 2 / (far - near);
|
||||
|
||||
return { {
|
||||
return {{
|
||||
{ rl, 0, 0, tx },
|
||||
{ 0, tb, 0, ty },
|
||||
{ 0, 0, fn, tz },
|
||||
{ 0, 0, 0, 1 },
|
||||
} };
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows, Cols,T>::ortho2D (T left , T right,
|
||||
T bottom, T top)
|
||||
util::ortho2D (T left, T right,
|
||||
T bottom, T top)
|
||||
{
|
||||
return ortho (left, right, bottom, top, -1, 1);
|
||||
return ortho (left, right, bottom, top, T{-1}, T{1});
|
||||
}
|
||||
|
||||
template util::matrix4f util::ortho2D (float, float, float, float);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::perspective (T fov, T aspect, range<T> Z)
|
||||
util::perspective (T fov, T aspect, range<T> Z)
|
||||
{
|
||||
CHECK_GE (Z.lo, 0);
|
||||
CHECK_GE (Z.hi, 0);
|
||||
@ -216,6 +191,8 @@ matrix<Rows,Cols,T>::perspective (T fov, T aspect, range<T> Z)
|
||||
} };
|
||||
}
|
||||
|
||||
template util::matrix4f util::perspective<float> (float, float, range<float>);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Emulates gluLookAt
|
||||
@ -225,11 +202,11 @@ matrix<Rows,Cols,T>::perspective (T fov, T aspect, range<T> Z)
|
||||
// Implemented for right handed world coordinates.
|
||||
//
|
||||
// Assumes 'up' is normalised.
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::look_at (const util::point<3,T> eye,
|
||||
const util::point<3,T> centre,
|
||||
const util::vector<3,T> up)
|
||||
util::look_at (const util::point<3,T> eye,
|
||||
const util::point<3,T> centre,
|
||||
const util::vector<3,T> up)
|
||||
{
|
||||
CHECK (is_normalised (up));
|
||||
|
||||
@ -244,23 +221,16 @@ matrix<Rows,Cols,T>::look_at (const util::point<3,T> eye,
|
||||
{ 0, 0, 0, 1 },
|
||||
}};
|
||||
|
||||
return rot * util::matrix4<T>::translation (0-eye);
|
||||
return rot * util::translation<T> (0-eye);
|
||||
}
|
||||
|
||||
template util::matrix4f util::look_at (util::point3f, util::point3f, util::vector3f);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::translation (util::vector<2,T> v)
|
||||
{
|
||||
return translation ({v.x, v.y, 0});
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::translation (util::vector<3,T> v)
|
||||
util::translation (util::vector<3,T> v)
|
||||
{
|
||||
return { {
|
||||
{ 1.f, 0.f, 0.f, v.x },
|
||||
@ -271,18 +241,24 @@ matrix<Rows,Cols,T>::translation (util::vector<3,T> v)
|
||||
}
|
||||
|
||||
|
||||
template util::matrix4f util::translation (util::vector3f);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::scale (T mag)
|
||||
util::scale (T mag)
|
||||
{
|
||||
return scale (vector<3,T> (mag));
|
||||
}
|
||||
|
||||
template util::matrix4f util::scale(float);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::scale (util::vector<3,T> v)
|
||||
util::scale (util::vector<3,T> v)
|
||||
{
|
||||
return { {
|
||||
{ v.x, 0.f, 0.f, 0.f },
|
||||
@ -292,11 +268,13 @@ matrix<Rows,Cols,T>::scale (util::vector<3,T> v)
|
||||
} };
|
||||
}
|
||||
|
||||
template util::matrix4f util::scale(util::vector3f);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <typename T>
|
||||
util::matrix4<T>
|
||||
matrix<Rows,Cols,T>::rotation (T angle, util::vector<3,T> about)
|
||||
util::rotation (T angle, util::vector<3,T> about)
|
||||
{
|
||||
CHECK (is_normalised (about));
|
||||
|
||||
@ -329,6 +307,7 @@ matrix<Rows,Cols,T>::rotation (T angle, util::vector<3,T> about)
|
||||
} };
|
||||
}
|
||||
|
||||
template util::matrix4f util::rotation (float, util::vector3f);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template struct util::matrix<2,2,float>;
|
||||
@ -345,7 +324,7 @@ template struct util::matrix<4,4,double>;
|
||||
// Uses the algorithm from:
|
||||
// "Extracting Euler Angles from a Rotation Matrix" by
|
||||
// Mike Day, Insomniac Games.
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
util::vector<3,T>
|
||||
util::to_euler (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
@ -372,24 +351,3 @@ util::to_euler (const matrix<Rows,Cols,T> &m)
|
||||
template util::vector<3,float> util::to_euler (const matrix<3,3,float>&);
|
||||
template util::vector<3,float> util::to_euler (const matrix<4,4,float>&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
std::ostream&
|
||||
util::operator<< (std::ostream &os, const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
os << "{ ";
|
||||
|
||||
for (size_t i = 0; i < Rows; ++i) {
|
||||
os << "{ ";
|
||||
std::copy_n (m[i], Cols, util::infix_iterator<float> (os, ", "));
|
||||
os << ((i == Rows - 1) ? " }" : " }, ");
|
||||
}
|
||||
|
||||
return os << " }";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template std::ostream& util::operator<< (std::ostream&, const matrix<4,4,float>&);
|
||||
template std::ostream& util::operator<< (std::ostream&, const matrix<4,4,double>&);
|
||||
|
421
matrix.hpp
421
matrix.hpp
@ -19,87 +19,109 @@
|
||||
|
||||
#include "point.hpp"
|
||||
#include "range.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
|
||||
namespace util {
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <
|
||||
std::size_t Rows,
|
||||
std::size_t Cols,
|
||||
typename T
|
||||
>
|
||||
struct matrix {
|
||||
static constexpr auto rows = Rows;
|
||||
static constexpr auto cols = Cols;
|
||||
|
||||
T values[Rows][Cols];
|
||||
using row_t = util::vector<Cols,T>;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
constexpr matrix () noexcept = default;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr matrix (const T(&_data)[Rows][Cols]) noexcept:
|
||||
values {}
|
||||
{
|
||||
static_assert (sizeof (*this) == sizeof (T) * Rows * Cols);
|
||||
for (std::size_t r = 0; r < Rows; ++r)
|
||||
for (std::size_t c = 0; c < Cols; ++c)
|
||||
values[r][c] = _data[r][c];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <std::size_t S, typename SelfT>
|
||||
constexpr matrix (const util::coord::base<S,T,SelfT> (&_data)[Rows]) noexcept
|
||||
{
|
||||
for (std::size_t r = 0; r < Rows; ++r)
|
||||
for (std::size_t c = 0; c < Cols; ++c)
|
||||
values[r][c] = _data[r][c];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// index operators return a pointer into the data array so that
|
||||
// multidimensional array syntax can be used transparently on this
|
||||
// type.
|
||||
constexpr T*
|
||||
operator[] (size_t idx) noexcept
|
||||
constexpr row_t& operator[] (std::size_t idx)& { return values[idx]; }
|
||||
constexpr const row_t& operator[] (std::size_t idx) const& { return values[idx]; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr row_t*
|
||||
data (void)& noexcept
|
||||
{
|
||||
return this->values[idx];
|
||||
return &values[0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr const T*
|
||||
operator[] (size_t idx) const noexcept
|
||||
constexpr const row_t*
|
||||
data (void) const& noexcept
|
||||
{
|
||||
return this->values[idx];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr T*
|
||||
data (void) noexcept
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr const T*
|
||||
data (void) const noexcept
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr const T*
|
||||
begin (void) const noexcept
|
||||
{
|
||||
return &(*this)[0][0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr const T*
|
||||
end (void) const noexcept
|
||||
{
|
||||
return &(*this)[Rows][0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr T*
|
||||
begin (void) noexcept
|
||||
{
|
||||
return &(*this)[0][0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr T*
|
||||
end (void) noexcept
|
||||
{
|
||||
return &(*this)[Rows][0];
|
||||
return &values[0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr auto
|
||||
cbegin (void) const noexcept
|
||||
begin (void) const& noexcept
|
||||
{
|
||||
return data ();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr auto
|
||||
begin (void)& noexcept
|
||||
{
|
||||
return data ();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr row_t*
|
||||
end (void)& noexcept
|
||||
{
|
||||
return &values[Rows];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr const row_t*
|
||||
end (void) const& noexcept
|
||||
{
|
||||
return &values[Rows];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr auto
|
||||
cbegin (void) const& noexcept
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr auto
|
||||
cend (void) const noexcept
|
||||
cend (void) const& noexcept
|
||||
{
|
||||
return end ();
|
||||
}
|
||||
@ -118,109 +140,166 @@ namespace util {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
vector<Rows,T> operator* (const vector<Rows,T>&) const;
|
||||
point<Rows,T> operator* (const point<Rows,T> &) const;
|
||||
template <typename VectorT>
|
||||
std::enable_if_t<is_coord_v<VectorT>, VectorT>
|
||||
operator* (const VectorT &rhs) const
|
||||
{
|
||||
VectorT out;
|
||||
|
||||
for (std::size_t r = 0; r < Rows; ++r)
|
||||
out[r] = dot (rhs, values[r]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool is_affine (void) const;
|
||||
|
||||
template <typename U>
|
||||
matrix<Rows,Cols,U>
|
||||
cast (void) const
|
||||
cast (void) const noexcept
|
||||
{
|
||||
util::matrix<Rows,Cols,T> out;
|
||||
matrix out;
|
||||
std::copy (cbegin (), cend (), std::begin (out));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Perspective matrices
|
||||
static matrix<4,4,T> ortho (T left, T right, T bottom, T top, T near, T far);
|
||||
static matrix<4,4,T> ortho2D (T left, T right, T bottom, T top);
|
||||
static matrix<4,4,T> perspective (T fov, T aspect, range<T> Z);
|
||||
static matrix<4,4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up);
|
||||
|
||||
// Affine matrices
|
||||
static matrix<4,4,T> translation (util::vector<2,T>);
|
||||
static matrix<4,4,T> translation (util::vector<3,T>);
|
||||
static matrix<4,4,T> scale (util::vector<3,T>);
|
||||
static matrix<4,4,T> scale (T);
|
||||
static matrix<4,4,T> rotation (T angle, util::vector<3,T> about);
|
||||
|
||||
// Constant matrices
|
||||
static constexpr matrix identity ();
|
||||
static constexpr matrix zeroes ();
|
||||
static constexpr
|
||||
matrix identity (void) noexcept
|
||||
{
|
||||
auto m = zeroes ();
|
||||
for (std::size_t i = 0; i < Rows; ++i)
|
||||
m[i][i] = 1;
|
||||
return m;
|
||||
}
|
||||
|
||||
static constexpr
|
||||
matrix zeroes (void) noexcept
|
||||
{
|
||||
matrix ret {};
|
||||
std::fill (std::begin (ret), std::end (ret), row_t{0});
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
row_t values[Rows];
|
||||
};
|
||||
|
||||
|
||||
// Perspective matrices
|
||||
template <typename T> matrix<4,4,T> ortho (T left, T right, T bottom, T top, T near, T far);
|
||||
template <typename T> matrix<4,4,T> ortho2D (T left, T right, T bottom, T top);
|
||||
template <typename T> matrix<4,4,T> perspective (T fov, T aspect, range<T> Z);
|
||||
template <typename T> matrix<4,4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up);
|
||||
|
||||
// Affine matrices
|
||||
template <typename T> matrix<4,4,T> translation (vector<3,T>);
|
||||
template <typename T> matrix<4,4,T> scale (vector<3,T>);
|
||||
template <typename T> matrix<4,4,T> scale (T);
|
||||
template <typename T> matrix<4,4,T> rotation (T angle, vector<3,T> about);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Convert an affine rotation matrix to euler angles.
|
||||
//
|
||||
// Results are undefined if the matrix is not purely a rotation matrix,
|
||||
// or if the dimension is not 3x3 or 4x4.
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
vector<3,T>
|
||||
to_euler (const matrix<Rows, Cols, T>&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// logical operations
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr
|
||||
bool
|
||||
operator== (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
|
||||
operator== (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
|
||||
{
|
||||
return std::equal (std::cbegin (a), std::cend (a), std::cbegin (b));
|
||||
}
|
||||
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
//-------------------------------------------------------------------------
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr
|
||||
bool
|
||||
operator!= (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
|
||||
operator!= (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// element operations
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr
|
||||
matrix<Rows,Cols,T>
|
||||
operator+ (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr
|
||||
matrix<Rows,Cols,T>
|
||||
operator- (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
|
||||
|
||||
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr
|
||||
matrix<Rows,Cols,T>
|
||||
div (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
|
||||
{
|
||||
matrix<Rows,Cols,T> out {};
|
||||
for (std::size_t r = 0; r < Rows; ++r)
|
||||
for (std::size_t c = 0; c < Cols; ++c)
|
||||
out[r][c] = a[r][c] / b[r][c];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr T
|
||||
max (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
T val = m[0][0];
|
||||
for (std::size_t r = 0; r < Rows; ++r)
|
||||
for (std::size_t c = 0; c < Cols; ++c)
|
||||
val = max (val, m[r][c]);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// scalar operations
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator* (const matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator/ (const matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator+ (const matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator- (const matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator* (const matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator/ (const matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator+ (const matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator- (const matrix<R,C,T>&, T);
|
||||
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator* (T, const matrix<R,C,T>&);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator/ (T, const matrix<R,C,T>&);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator+ (T, const matrix<R,C,T>&);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator- (T, const matrix<R,C,T>&);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator* (T, const matrix<R,C,T>&);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator/ (T, const matrix<R,C,T>&);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator+ (T, const matrix<R,C,T>&);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T> operator- (T, const matrix<R,C,T>&);
|
||||
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator*= (matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator/= (matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator+= (matrix<R,C,T>&, T);
|
||||
template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator-= (matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T>& operator*= (matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T>& operator/= (matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T>& operator+= (matrix<R,C,T>&, T);
|
||||
template <std::size_t R, std::size_t C, typename T> constexpr matrix<R,C,T>& operator-= (matrix<R,C,T>&, T);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// matrix operations
|
||||
template <
|
||||
size_t R1, size_t C1,
|
||||
size_t R2, size_t C2,
|
||||
std::size_t R1, //int C1,
|
||||
std::size_t RC, //int R2,
|
||||
std::size_t C2,
|
||||
typename T
|
||||
>
|
||||
constexpr
|
||||
matrix<R1,C2,T>
|
||||
operator* (const matrix<R1,C1,T> &a, const matrix<R2,C2,T> &b) noexcept
|
||||
operator* (const matrix<R1,RC,T>&a, const matrix<RC,C2,T>&b)
|
||||
{
|
||||
static_assert (R2 == C1);
|
||||
|
||||
matrix<R1,C2,T> res {0};
|
||||
matrix<R1,C2,T> res {};
|
||||
|
||||
// TODO: iterating over r,c rather than c,r will cause an ICE with
|
||||
// clang#xxxx: 'X86 DAG->DAG Instruction Selection'.
|
||||
@ -228,11 +307,11 @@ namespace util {
|
||||
// this is likely related to gold and LTO support. for the time being
|
||||
// we switch the orders because it appears to confuse the optimiser
|
||||
// sufficiently. :(
|
||||
for (size_t c = 0; c < C2; ++c) {
|
||||
for (size_t r = 0; r < R1; ++r) {
|
||||
T accum{0};
|
||||
for (std::size_t c = 0; c < C2; ++c) {
|
||||
for (std::size_t r = 0; r < R1; ++r) {
|
||||
T accum {0};
|
||||
|
||||
for (size_t i = 0; i < R2; ++i)
|
||||
for (std::size_t i = 0; i < RC; ++i)
|
||||
accum += a[r][i] * b[i][c];
|
||||
|
||||
res[r][c] = accum;
|
||||
@ -245,8 +324,8 @@ namespace util {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <
|
||||
size_t R1, size_t C1,
|
||||
size_t R2, size_t C2,
|
||||
std::size_t R1, std::size_t C1,
|
||||
std::size_t R2, std::size_t C2,
|
||||
typename T
|
||||
>
|
||||
constexpr
|
||||
@ -256,36 +335,128 @@ namespace util {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
T
|
||||
determinant (const matrix<Rows,Cols,T>&);
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Rows,Cols,T>
|
||||
inverse (const matrix<Rows,Cols,T>&);
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Cols,Rows,T>
|
||||
transposed (const matrix<Rows,Cols,T>&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Rows,Cols,T>
|
||||
abs (const matrix<Rows,Cols,T>&);
|
||||
abs (const matrix<Rows,Cols,T> &src)
|
||||
{
|
||||
matrix<Rows,Cols,T> dst;
|
||||
for (size_t r = 0; r < Rows; ++r)
|
||||
dst[r] = abs (src[r]);
|
||||
return dst;
|
||||
}
|
||||
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
T
|
||||
sum (const matrix<Rows,Cols,T>&);
|
||||
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
constexpr T
|
||||
sum (const matrix<Rows,Cols,T> &src)
|
||||
{
|
||||
util::vector<Rows,T> accum {};
|
||||
for (size_t r = 0; r < Rows; ++r)
|
||||
accum[r] = sum (src[r]);
|
||||
return sum (accum);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#define MATRIX_ELEMENT_OP(OP) \
|
||||
template <std::size_t Rows, std::size_t Cols, typename T> \
|
||||
constexpr \
|
||||
matrix<Rows,Cols,T> \
|
||||
operator OP ( \
|
||||
const matrix<Rows,Cols,T> &a, \
|
||||
const matrix<Rows,Cols,T> &b) \
|
||||
{ \
|
||||
matrix<Rows,Cols,T> res {}; \
|
||||
\
|
||||
for (std::size_t i = 0; i < a.rows; ++i) \
|
||||
for (std::size_t j = 0; j < a.cols; ++j) \
|
||||
res[i][j] = a[i][j] OP b[i][j]; \
|
||||
\
|
||||
return res; \
|
||||
}
|
||||
|
||||
MATRIX_ELEMENT_OP(-)
|
||||
MATRIX_ELEMENT_OP(+)
|
||||
|
||||
#undef MATRIX_ELEMENT_OP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#define MATRIX_SCALAR_OP(OP) \
|
||||
template <std::size_t Rows, std::size_t Cols, typename T> \
|
||||
constexpr \
|
||||
matrix<Rows,Cols,T> \
|
||||
operator OP (const matrix<Rows,Cols,T> &m, const T t) \
|
||||
{ \
|
||||
matrix<Rows,Cols,T> res {}; \
|
||||
\
|
||||
std::transform ( \
|
||||
std::cbegin (m), \
|
||||
std::cend (m), \
|
||||
std::begin (res), \
|
||||
[&t] (auto x) { return x OP t; } \
|
||||
); \
|
||||
\
|
||||
return res; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
template <std::size_t Rows, std::size_t Cols, typename T> \
|
||||
constexpr \
|
||||
matrix<Rows,Cols,T> \
|
||||
operator OP (const T t, const matrix<Rows,Cols,T> &m) \
|
||||
{ \
|
||||
return m OP t; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
template <std::size_t Rows, std::size_t Cols, typename T> \
|
||||
constexpr \
|
||||
matrix<Rows,Cols,T>& \
|
||||
operator OP##= (matrix<Rows,Cols,T> &m, T t) \
|
||||
{ \
|
||||
std::transform ( \
|
||||
std::cbegin (m), \
|
||||
std::cend (m), \
|
||||
std::begin (m), \
|
||||
[&t] (auto x) { return x OP t; } \
|
||||
); \
|
||||
\
|
||||
return m; \
|
||||
}
|
||||
|
||||
MATRIX_SCALAR_OP(*)
|
||||
MATRIX_SCALAR_OP(/)
|
||||
MATRIX_SCALAR_OP(+)
|
||||
MATRIX_SCALAR_OP(-)
|
||||
|
||||
#undef MATRIX_SCALAR_OP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T> using matrix3 = matrix<3,3,T>;
|
||||
template <typename T> using matrix4 = matrix<4,4,T>;
|
||||
|
||||
template <size_t Rows, size_t Cols> using matrixf = matrix<Rows,Cols,float>;
|
||||
template <size_t Rows, size_t Cols> using matrixd = matrix<Rows,Cols,double>;
|
||||
template <std::size_t Rows, std::size_t Cols> using matrixf = matrix<Rows,Cols,float>;
|
||||
template <std::size_t Rows, std::size_t Cols> using matrixd = matrix<Rows,Cols,double>;
|
||||
|
||||
typedef matrix<2,2,float> matrix2f;
|
||||
typedef matrix<2,2,double> matrix2d;
|
||||
@ -298,10 +469,18 @@ namespace util {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
std::ostream& operator<< (std::ostream&, const matrix<Rows,Cols,T>&);
|
||||
}
|
||||
|
||||
#include "matrix.ipp"
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
std::ostream&
|
||||
operator<< (std::ostream &os, const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
os << '[';
|
||||
std::copy (
|
||||
std::cbegin (m),
|
||||
std::cend (m),
|
||||
util::infix_iterator<decltype(m[0])> (os, ", ")
|
||||
);
|
||||
return os << ']';
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
165
matrix.ipp
165
matrix.ipp
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2011-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __UTIL_MATRIX_IPP
|
||||
#error
|
||||
#endif
|
||||
|
||||
#define __UTIL_MATRIX_IPP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define MATRIX_ELEMENT_OP(OP) \
|
||||
template <size_t Rows, size_t Cols, typename T> \
|
||||
constexpr \
|
||||
util::matrix<Rows,Cols,T> \
|
||||
util::operator OP ( \
|
||||
const util::matrix<Rows,Cols,T> &a, \
|
||||
const util::matrix<Rows,Cols,T> &b) \
|
||||
{ \
|
||||
util::matrix<Rows,Cols,T> res {}; \
|
||||
\
|
||||
for (size_t i = 0; i < a.rows; ++i) \
|
||||
for (size_t j = 0; j < a.cols; ++j) \
|
||||
res[i][j] = a[i][j] OP b[i][j]; \
|
||||
\
|
||||
return res; \
|
||||
}
|
||||
|
||||
MATRIX_ELEMENT_OP(-)
|
||||
MATRIX_ELEMENT_OP(+)
|
||||
|
||||
#undef MATRIX_ELEMENT_OP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define MATRIX_SCALAR_OP(OP) \
|
||||
template <size_t Rows, size_t Cols, typename T> \
|
||||
constexpr \
|
||||
util::matrix<Rows,Cols,T> \
|
||||
util::operator OP (const util::matrix<Rows,Cols,T> &m, const T t) \
|
||||
{ \
|
||||
util::matrix<Rows,Cols,T> res {}; \
|
||||
\
|
||||
std::transform ( \
|
||||
std::cbegin (m), \
|
||||
std::cend (m), \
|
||||
std::begin (res), \
|
||||
[&t] (auto x) { return x OP t; } \
|
||||
); \
|
||||
\
|
||||
return res; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
template <size_t Rows, size_t Cols, typename T> \
|
||||
constexpr \
|
||||
util::matrix<Rows,Cols,T> \
|
||||
util::operator OP (const T t, const util::matrix<Rows,Cols,T> &m) \
|
||||
{ \
|
||||
return m OP t; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
template <size_t Rows, size_t Cols, typename T> \
|
||||
constexpr \
|
||||
util::matrix<Rows,Cols,T>& \
|
||||
util::operator OP##= (util::matrix<Rows,Cols,T> &m, T t) \
|
||||
{ \
|
||||
std::transform ( \
|
||||
std::cbegin (m), \
|
||||
std::cend (m), \
|
||||
std::begin (m), \
|
||||
[&t] (auto x) { return x OP t; } \
|
||||
); \
|
||||
\
|
||||
return m; \
|
||||
}
|
||||
|
||||
|
||||
MATRIX_SCALAR_OP(*)
|
||||
MATRIX_SCALAR_OP(/)
|
||||
MATRIX_SCALAR_OP(+)
|
||||
MATRIX_SCALAR_OP(-)
|
||||
|
||||
#undef MATRIX_SCALAR_OP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
util::matrix<Rows,Cols,T>
|
||||
util::matrix<Rows,Cols,T>::zeroes (void)
|
||||
{
|
||||
return {0};
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
util::matrix<Rows,Cols,T>
|
||||
util::matrix<Rows,Cols,T>::identity (void)
|
||||
{
|
||||
static_assert (Rows == Cols);
|
||||
|
||||
auto m = zeroes ();
|
||||
for (size_t i = 0; i < Rows; ++i)
|
||||
m[i][i] = 1;
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
bool
|
||||
util::operator== (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
|
||||
{
|
||||
return std::equal (std::cbegin (a), std::cend (a), std::cbegin (b));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
bool
|
||||
util::operator!= (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
util::matrix<Rows,Cols,T>
|
||||
util::abs (const util::matrix<Rows,Cols,T> &src)
|
||||
{
|
||||
util::matrix<Rows,Cols,T> dst;
|
||||
std::transform (std::cbegin (src), std::cend (src), std::begin (dst), util::abs<T>);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
constexpr
|
||||
T
|
||||
util::sum (const util::matrix<Rows, Cols,T> &src)
|
||||
{
|
||||
return sum (std::cbegin (src), std::cend (src));
|
||||
}
|
12
matrix2.cpp
12
matrix2.cpp
@ -20,7 +20,7 @@ using util::matrix;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
T
|
||||
util::determinant (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
@ -34,16 +34,16 @@ template double util::determinant (const matrix<2,2,double>&);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Rows,Cols,T>
|
||||
util::inverse (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
static_assert (Rows == 2 && Cols == 2);
|
||||
|
||||
return matrix<2,2,T> {
|
||||
m[1][1], -m[0][1],
|
||||
-m[1][0], m[0][0]
|
||||
} / determinant (m);
|
||||
return matrix<2,2,T> {{
|
||||
{ m[1][1], -m[0][1], },
|
||||
{ -m[1][0], m[0][0], },
|
||||
}} / determinant (m);
|
||||
}
|
||||
|
||||
|
||||
|
28
matrix3.cpp
28
matrix3.cpp
@ -14,13 +14,13 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./matrix.hpp"
|
||||
#include "matrix.hpp"
|
||||
|
||||
using util::matrix;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
T
|
||||
util::determinant (const matrix<Rows,Cols,T>& m)
|
||||
{
|
||||
@ -36,25 +36,25 @@ template double util::determinant (const matrix<3,3,double>&);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Rows,Cols,T>
|
||||
util::inverse (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
static_assert (Rows == 3 && Cols == 3);
|
||||
|
||||
return matrix<3,3,T> {
|
||||
m[1][1] * m[2][2] - m[2][1] * m[1][2],
|
||||
m[0][2] * m[2][1] - m[0][1] * m[2][2],
|
||||
m[0][1] * m[1][2] - m[0][2] * m[1][1],
|
||||
return matrix<3,3,T> {{
|
||||
{ m[1][1] * m[2][2] - m[2][1] * m[1][2],
|
||||
m[0][2] * m[2][1] - m[0][1] * m[2][2],
|
||||
m[0][1] * m[1][2] - m[0][2] * m[1][1], },
|
||||
|
||||
m[1][2] * m[2][0] - m[1][0] * m[2][2],
|
||||
m[0][0] * m[2][2] - m[0][2] * m[2][0],
|
||||
m[1][0] * m[0][2] - m[0][0] * m[1][2],
|
||||
{ m[1][2] * m[2][0] - m[1][0] * m[2][2],
|
||||
m[0][0] * m[2][2] - m[0][2] * m[2][0],
|
||||
m[1][0] * m[0][2] - m[0][0] * m[1][2], },
|
||||
|
||||
m[1][0] * m[2][1] - m[2][0] * m[1][1],
|
||||
m[2][0] * m[0][1] - m[0][0] * m[2][1],
|
||||
m[0][0] * m[1][1] - m[1][0] * m[0][1],
|
||||
} / determinant (m);
|
||||
{ m[1][0] * m[2][1] - m[2][0] * m[1][1],
|
||||
m[2][0] * m[0][1] - m[0][0] * m[2][1],
|
||||
m[0][0] * m[1][1] - m[1][0] * m[0][1], },
|
||||
}} / determinant (m);
|
||||
}
|
||||
|
||||
template util::matrix<3,3,float> util::inverse (const matrix<3,3,float>&);
|
||||
|
135
matrix4.cpp
135
matrix4.cpp
@ -20,7 +20,7 @@ using util::matrix;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
T
|
||||
util::determinant (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
@ -45,30 +45,125 @@ template double util::determinant (const matrix<4,4,double>&);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t Rows, size_t Cols, typename T>
|
||||
template <std::size_t Rows, std::size_t Cols, typename T>
|
||||
matrix<Rows,Cols,T>
|
||||
util::inverse (const matrix<Rows,Cols,T> &m)
|
||||
{
|
||||
static_assert (Rows == 4 && Cols == 4);
|
||||
|
||||
return matrix<4,4,T> {
|
||||
m[1][2]*m[2][3]*m[3][1] - m[1][3]*m[2][2]*m[3][1] + m[1][3]*m[2][1]*m[3][2] - m[1][1]*m[2][3]*m[3][2] - m[1][2]*m[2][1]*m[3][3] + m[1][1]*m[2][2]*m[3][3],
|
||||
m[0][3]*m[2][2]*m[3][1] - m[0][2]*m[2][3]*m[3][1] - m[0][3]*m[2][1]*m[3][2] + m[0][1]*m[2][3]*m[3][2] + m[0][2]*m[2][1]*m[3][3] - m[0][1]*m[2][2]*m[3][3],
|
||||
m[0][2]*m[1][3]*m[3][1] - m[0][3]*m[1][2]*m[3][1] + m[0][3]*m[1][1]*m[3][2] - m[0][1]*m[1][3]*m[3][2] - m[0][2]*m[1][1]*m[3][3] + m[0][1]*m[1][2]*m[3][3],
|
||||
m[0][3]*m[1][2]*m[2][1] - m[0][2]*m[1][3]*m[2][1] - m[0][3]*m[1][1]*m[2][2] + m[0][1]*m[1][3]*m[2][2] + m[0][2]*m[1][1]*m[2][3] - m[0][1]*m[1][2]*m[2][3],
|
||||
m[1][3]*m[2][2]*m[3][0] - m[1][2]*m[2][3]*m[3][0] - m[1][3]*m[2][0]*m[3][2] + m[1][0]*m[2][3]*m[3][2] + m[1][2]*m[2][0]*m[3][3] - m[1][0]*m[2][2]*m[3][3],
|
||||
m[0][2]*m[2][3]*m[3][0] - m[0][3]*m[2][2]*m[3][0] + m[0][3]*m[2][0]*m[3][2] - m[0][0]*m[2][3]*m[3][2] - m[0][2]*m[2][0]*m[3][3] + m[0][0]*m[2][2]*m[3][3],
|
||||
m[0][3]*m[1][2]*m[3][0] - m[0][2]*m[1][3]*m[3][0] - m[0][3]*m[1][0]*m[3][2] + m[0][0]*m[1][3]*m[3][2] + m[0][2]*m[1][0]*m[3][3] - m[0][0]*m[1][2]*m[3][3],
|
||||
m[0][2]*m[1][3]*m[2][0] - m[0][3]*m[1][2]*m[2][0] + m[0][3]*m[1][0]*m[2][2] - m[0][0]*m[1][3]*m[2][2] - m[0][2]*m[1][0]*m[2][3] + m[0][0]*m[1][2]*m[2][3],
|
||||
m[1][1]*m[2][3]*m[3][0] - m[1][3]*m[2][1]*m[3][0] + m[1][3]*m[2][0]*m[3][1] - m[1][0]*m[2][3]*m[3][1] - m[1][1]*m[2][0]*m[3][3] + m[1][0]*m[2][1]*m[3][3],
|
||||
m[0][3]*m[2][1]*m[3][0] - m[0][1]*m[2][3]*m[3][0] - m[0][3]*m[2][0]*m[3][1] + m[0][0]*m[2][3]*m[3][1] + m[0][1]*m[2][0]*m[3][3] - m[0][0]*m[2][1]*m[3][3],
|
||||
m[0][1]*m[1][3]*m[3][0] - m[0][3]*m[1][1]*m[3][0] + m[0][3]*m[1][0]*m[3][1] - m[0][0]*m[1][3]*m[3][1] - m[0][1]*m[1][0]*m[3][3] + m[0][0]*m[1][1]*m[3][3],
|
||||
m[0][3]*m[1][1]*m[2][0] - m[0][1]*m[1][3]*m[2][0] - m[0][3]*m[1][0]*m[2][1] + m[0][0]*m[1][3]*m[2][1] + m[0][1]*m[1][0]*m[2][3] - m[0][0]*m[1][1]*m[2][3],
|
||||
m[1][2]*m[2][1]*m[3][0] - m[1][1]*m[2][2]*m[3][0] - m[1][2]*m[2][0]*m[3][1] + m[1][0]*m[2][2]*m[3][1] + m[1][1]*m[2][0]*m[3][2] - m[1][0]*m[2][1]*m[3][2],
|
||||
m[0][1]*m[2][2]*m[3][0] - m[0][2]*m[2][1]*m[3][0] + m[0][2]*m[2][0]*m[3][1] - m[0][0]*m[2][2]*m[3][1] - m[0][1]*m[2][0]*m[3][2] + m[0][0]*m[2][1]*m[3][2],
|
||||
m[0][2]*m[1][1]*m[3][0] - m[0][1]*m[1][2]*m[3][0] - m[0][2]*m[1][0]*m[3][1] + m[0][0]*m[1][2]*m[3][1] + m[0][1]*m[1][0]*m[3][2] - m[0][0]*m[1][1]*m[3][2],
|
||||
m[0][1]*m[1][2]*m[2][0] - m[0][2]*m[1][1]*m[2][0] + m[0][2]*m[1][0]*m[2][1] - m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] + m[0][0]*m[1][1]*m[2][2],
|
||||
} / determinant (m);
|
||||
return matrix<4,4,T> {{
|
||||
{ m[1][2]*m[2][3]*m[3][1]
|
||||
-m[1][3]*m[2][2]*m[3][1]
|
||||
+m[1][3]*m[2][1]*m[3][2]
|
||||
-m[1][1]*m[2][3]*m[3][2]
|
||||
-m[1][2]*m[2][1]*m[3][3]
|
||||
+m[1][1]*m[2][2]*m[3][3],
|
||||
|
||||
m[0][3]*m[2][2]*m[3][1]
|
||||
-m[0][2]*m[2][3]*m[3][1]
|
||||
-m[0][3]*m[2][1]*m[3][2]
|
||||
+m[0][1]*m[2][3]*m[3][2]
|
||||
+m[0][2]*m[2][1]*m[3][3]
|
||||
-m[0][1]*m[2][2]*m[3][3],
|
||||
|
||||
m[0][2]*m[1][3]*m[3][1]
|
||||
-m[0][3]*m[1][2]*m[3][1]
|
||||
+m[0][3]*m[1][1]*m[3][2]
|
||||
-m[0][1]*m[1][3]*m[3][2]
|
||||
-m[0][2]*m[1][1]*m[3][3]
|
||||
+m[0][1]*m[1][2]*m[3][3],
|
||||
|
||||
m[0][3]*m[1][2]*m[2][1]
|
||||
-m[0][2]*m[1][3]*m[2][1]
|
||||
-m[0][3]*m[1][1]*m[2][2]
|
||||
+m[0][1]*m[1][3]*m[2][2]
|
||||
+m[0][2]*m[1][1]*m[2][3]
|
||||
-m[0][1]*m[1][2]*m[2][3], },
|
||||
|
||||
{ m[1][3]*m[2][2]*m[3][0]
|
||||
-m[1][2]*m[2][3]*m[3][0]
|
||||
-m[1][3]*m[2][0]*m[3][2]
|
||||
+m[1][0]*m[2][3]*m[3][2]
|
||||
+m[1][2]*m[2][0]*m[3][3]
|
||||
-m[1][0]*m[2][2]*m[3][3],
|
||||
|
||||
m[0][2]*m[2][3]*m[3][0]
|
||||
-m[0][3]*m[2][2]*m[3][0]
|
||||
+m[0][3]*m[2][0]*m[3][2]
|
||||
-m[0][0]*m[2][3]*m[3][2]
|
||||
-m[0][2]*m[2][0]*m[3][3]
|
||||
+m[0][0]*m[2][2]*m[3][3],
|
||||
|
||||
m[0][3]*m[1][2]*m[3][0]
|
||||
-m[0][2]*m[1][3]*m[3][0]
|
||||
-m[0][3]*m[1][0]*m[3][2]
|
||||
+m[0][0]*m[1][3]*m[3][2]
|
||||
+m[0][2]*m[1][0]*m[3][3]
|
||||
-m[0][0]*m[1][2]*m[3][3],
|
||||
|
||||
m[0][2]*m[1][3]*m[2][0]
|
||||
-m[0][3]*m[1][2]*m[2][0]
|
||||
+m[0][3]*m[1][0]*m[2][2]
|
||||
-m[0][0]*m[1][3]*m[2][2]
|
||||
-m[0][2]*m[1][0]*m[2][3]
|
||||
+m[0][0]*m[1][2]*m[2][3], },
|
||||
|
||||
{ m[1][1]*m[2][3]*m[3][0]
|
||||
-m[1][3]*m[2][1]*m[3][0]
|
||||
+m[1][3]*m[2][0]*m[3][1]
|
||||
-m[1][0]*m[2][3]*m[3][1]
|
||||
-m[1][1]*m[2][0]*m[3][3]
|
||||
+m[1][0]*m[2][1]*m[3][3],
|
||||
|
||||
m[0][3]*m[2][1]*m[3][0]
|
||||
-m[0][1]*m[2][3]*m[3][0]
|
||||
-m[0][3]*m[2][0]*m[3][1]
|
||||
+m[0][0]*m[2][3]*m[3][1]
|
||||
+m[0][1]*m[2][0]*m[3][3]
|
||||
-m[0][0]*m[2][1]*m[3][3],
|
||||
|
||||
m[0][1]*m[1][3]*m[3][0]
|
||||
-m[0][3]*m[1][1]*m[3][0]
|
||||
+m[0][3]*m[1][0]*m[3][1]
|
||||
-m[0][0]*m[1][3]*m[3][1]
|
||||
-m[0][1]*m[1][0]*m[3][3]
|
||||
+m[0][0]*m[1][1]*m[3][3],
|
||||
|
||||
m[0][3]*m[1][1]*m[2][0]
|
||||
-m[0][1]*m[1][3]*m[2][0]
|
||||
-m[0][3]*m[1][0]*m[2][1]
|
||||
+m[0][0]*m[1][3]*m[2][1]
|
||||
+m[0][1]*m[1][0]*m[2][3]
|
||||
-m[0][0]*m[1][1]*m[2][3], },
|
||||
|
||||
{ m[1][2]*m[2][1]*m[3][0]
|
||||
-m[1][1]*m[2][2]*m[3][0]
|
||||
-m[1][2]*m[2][0]*m[3][1]
|
||||
+m[1][0]*m[2][2]*m[3][1]
|
||||
+m[1][1]*m[2][0]*m[3][2]
|
||||
-m[1][0]*m[2][1]*m[3][2],
|
||||
|
||||
m[0][1]*m[2][2]*m[3][0]
|
||||
-m[0][2]*m[2][1]*m[3][0]
|
||||
+m[0][2]*m[2][0]*m[3][1]
|
||||
-m[0][0]*m[2][2]*m[3][1]
|
||||
-m[0][1]*m[2][0]*m[3][2]
|
||||
+m[0][0]*m[2][1]*m[3][2],
|
||||
|
||||
m[0][2]*m[1][1]*m[3][0]
|
||||
-m[0][1]*m[1][2]*m[3][0]
|
||||
-m[0][2]*m[1][0]*m[3][1]
|
||||
+m[0][0]*m[1][2]*m[3][1]
|
||||
+m[0][1]*m[1][0]*m[3][2]
|
||||
-m[0][0]*m[1][1]*m[3][2],
|
||||
|
||||
m[0][1]*m[1][2]*m[2][0]
|
||||
-m[0][2]*m[1][1]*m[2][0]
|
||||
+m[0][2]*m[1][0]*m[2][1]
|
||||
-m[0][0]*m[1][2]*m[2][1]
|
||||
-m[0][1]*m[1][0]*m[2][2]
|
||||
+m[0][0]*m[1][1]*m[2][2], }
|
||||
}} / determinant (m);
|
||||
}
|
||||
|
||||
template util::matrix<4,4,float> util::inverse (const matrix<4,4,float>&);
|
||||
|
@ -14,14 +14,14 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./circular.hpp"
|
||||
#include "circular.hpp"
|
||||
|
||||
#include "../system.hpp"
|
||||
#include "../../debug.hpp"
|
||||
#include "../../except.hpp"
|
||||
#include "../../maths.hpp"
|
||||
#include "../../posix/except.hpp"
|
||||
#include "../../raii.hpp"
|
||||
#include "../../random.hpp"
|
||||
#include "../system.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
@ -54,7 +54,8 @@ tmpname (std::string &str, size_t length)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
circular::circular (size_t bytes)
|
||||
template <typename ValueT>
|
||||
circular<ValueT>::circular (size_t bytes)
|
||||
{
|
||||
bytes = max (bytes, sizeof (value_type));
|
||||
bytes = round_up (bytes, pagesize ());
|
||||
@ -84,14 +85,16 @@ circular::circular (size_t bytes)
|
||||
|
||||
// embiggen to the desired size
|
||||
if (ftruncate (fd, bytes))
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
// pre-allocate a sufficiently large virtual memory block. it doesn't
|
||||
// matter much what flags we use because we'll just be overwriting it
|
||||
// shortly.
|
||||
m_begin = reinterpret_cast<char*> (mmap (nullptr, bytes * 2, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
m_begin = reinterpret_cast<ValueT*> (
|
||||
mmap (nullptr, bytes * 2, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
|
||||
);
|
||||
if (MAP_FAILED == m_begin)
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
// preemptively setup an unmapping object in case the remapping fails
|
||||
util::scoped_function unmapper ([this, bytes] (void) { munmap (m_begin, bytes); });
|
||||
@ -101,11 +104,11 @@ circular::circular (size_t bytes)
|
||||
auto prot = PROT_READ | PROT_WRITE;
|
||||
auto flag = MAP_FIXED | MAP_SHARED;
|
||||
|
||||
m_begin = reinterpret_cast<char*> (mmap (m_begin, bytes, prot, flag, fd, 0));
|
||||
m_end = reinterpret_cast<char*> (mmap (m_begin + bytes, bytes, prot, flag, fd, 0));
|
||||
m_begin = reinterpret_cast<ValueT*> (mmap (m_begin, bytes, prot, flag, fd, 0));
|
||||
m_end = reinterpret_cast<ValueT*> (mmap (m_begin + bytes, bytes, prot, flag, fd, 0));
|
||||
|
||||
if (m_begin == MAP_FAILED || m_end == MAP_FAILED)
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
// all went well, disarm the failsafe
|
||||
unmapper.clear ();
|
||||
@ -113,7 +116,8 @@ circular::circular (size_t bytes)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
circular::~circular ()
|
||||
template <typename ValueT>
|
||||
circular<ValueT>::~circular ()
|
||||
{
|
||||
auto res = munmap (m_begin, 2 * (m_end - m_begin));
|
||||
(void)res;
|
||||
@ -122,24 +126,61 @@ circular::~circular ()
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
char*
|
||||
circular::begin (void)&
|
||||
template <typename ValueT>
|
||||
ValueT*
|
||||
circular<ValueT>::begin (void)&
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
char*
|
||||
circular::end (void)&
|
||||
template <typename ValueT>
|
||||
ValueT*
|
||||
circular<ValueT>::end (void)&
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename ValueT>
|
||||
size_t
|
||||
circular::size (void) const
|
||||
circular<ValueT>::size (void) const
|
||||
{
|
||||
return m_end - m_begin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename ValueT>
|
||||
typename circular<ValueT>::iterator
|
||||
circular<ValueT>::constrain (iterator cursor)
|
||||
{
|
||||
CHECK_LIMIT (cursor, m_begin, m_begin + 2 * size ());
|
||||
|
||||
return m_begin + (cursor - m_begin) % size ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename ValueT>
|
||||
util::view<typename circular<ValueT>::iterator>
|
||||
circular<ValueT>::constrain (util::view<iterator> window)
|
||||
{
|
||||
CHECK_LIMIT (window.begin (), m_begin, m_begin + 2 * size ());
|
||||
CHECK_LIMIT (window.end (), m_begin, m_begin + 2 * size ());
|
||||
|
||||
auto first = window.begin ();
|
||||
auto last = first + window.size ();
|
||||
util::view res { first, last };
|
||||
|
||||
CHECK_EQ (res.size (), window.size ());
|
||||
CHECK_LE (res.begin (), res.end ());
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template class util::memory::buffer::circular<char>;
|
||||
template class util::memory::buffer::circular<uint8_t>;
|
||||
|
@ -17,15 +17,20 @@
|
||||
#ifndef __UTIL_MEMORY_BUFFER_CIRCULAR_HPP
|
||||
#define __UTIL_MEMORY_BUFFER_CIRCULAR_HPP
|
||||
|
||||
#include "../../view.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace util::memory::buffer {
|
||||
// buffer size is advisory and will likely depend on page size. the user
|
||||
// must check the size after creation if this field is important for
|
||||
// their usage.
|
||||
template <typename ValueT>
|
||||
class circular {
|
||||
public:
|
||||
using value_type = char;
|
||||
using value_type = ValueT;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = const value_type*;
|
||||
|
||||
explicit circular (size_t bytes);
|
||||
~circular ();
|
||||
@ -35,19 +40,26 @@ namespace util::memory::buffer {
|
||||
circular& operator= (const circular&) = delete;
|
||||
circular& operator= (circular&&) = delete;
|
||||
|
||||
char& operator[] (size_t)&;
|
||||
const char& operator[] (size_t) const&;
|
||||
value_type& operator[] (size_t)&;
|
||||
const value_type& operator[] (size_t) const&;
|
||||
|
||||
char* begin (void)&;
|
||||
char* end (void)&;
|
||||
iterator begin (void)&;
|
||||
iterator end (void)&;
|
||||
|
||||
const char* begin (void) const&;
|
||||
const char* end (void) const&;
|
||||
const_iterator begin (void) const&;
|
||||
const_iterator end (void) const&;
|
||||
|
||||
size_t size (void) const;
|
||||
|
||||
/// rebases the pointer so that it points to within the first
|
||||
/// repetition of the data buffer.
|
||||
iterator constrain (iterator);
|
||||
/// rebases a pair of pointers so they fall within a contiguous span of
|
||||
/// the data buffer.
|
||||
util::view<iterator> constrain (util::view<iterator>);
|
||||
|
||||
private:
|
||||
char *m_begin, *m_end;
|
||||
value_type *m_begin, *m_end;
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -14,13 +14,13 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./paged.hpp"
|
||||
#include "paged.hpp"
|
||||
|
||||
#include "../system.hpp"
|
||||
#include "../../except.hpp"
|
||||
#include "../../cast.hpp"
|
||||
#include "../../maths.hpp"
|
||||
#include "../../pointer.hpp"
|
||||
#include "../../cast.hpp"
|
||||
#include "../../posix/except.hpp"
|
||||
#include "../system.hpp"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
@ -37,7 +37,7 @@ paged::paged (size_t bytes, size_t _window):
|
||||
);
|
||||
|
||||
if (m_begin == MAP_FAILED)
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
// remap the initial window with read/write permissions
|
||||
m_cursor = m_begin + round_up (min (m_window, bytes), pagesize ());
|
||||
@ -45,7 +45,7 @@ paged::paged (size_t bytes, size_t _window):
|
||||
m_cursor - m_begin,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
// record the nominal end address
|
||||
m_end = m_begin + round_up (bytes, pagesize ());
|
||||
@ -110,7 +110,7 @@ paged::commit (char *cursor)
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1, 0))
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
m_cursor = cursor;
|
||||
}
|
||||
@ -137,7 +137,7 @@ paged::release (char *desired)
|
||||
PROT_NONE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1, 0))
|
||||
errno_error::throw_code ();
|
||||
posix::error::throw_code ();
|
||||
|
||||
m_cursor = desired;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./deleter.hpp"
|
||||
#include "deleter.hpp"
|
||||
|
||||
using util::memory::owner_deleter;
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./system.hpp"
|
||||
#include "system.hpp"
|
||||
|
||||
#include "../except.hpp"
|
||||
#include "../cast.hpp"
|
||||
#include "../posix/except.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -28,11 +28,7 @@ util::memory::pagesize (void)
|
||||
static size_t val;
|
||||
|
||||
if (!val) {
|
||||
auto res = sysconf (_SC_PAGE_SIZE);
|
||||
if (res == -1)
|
||||
errno_error::throw_code ();
|
||||
|
||||
val = sign_cast<unsigned long> (res);
|
||||
val = sign_cast<unsigned long> (posix::error::try_value (sysconf (_SC_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
return val;
|
||||
|
17
parse.cpp
17
parse.cpp
@ -14,7 +14,9 @@
|
||||
* Copyright 2017 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "./parse.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
#include "cast.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
@ -69,9 +71,9 @@ c_fparse (const char *first, const char *last)
|
||||
#define C_PARSE(T, KLASS) \
|
||||
template <> \
|
||||
T \
|
||||
util::parse<T> (const char *first, const char *last) \
|
||||
util::parse<T> (util::view<const char *> str) \
|
||||
{ \
|
||||
return c_ ## KLASS ## parse<T> (first, last); \
|
||||
return c_ ## KLASS ## parse<T> (std::cbegin (str), std::cend (str)); \
|
||||
}
|
||||
|
||||
|
||||
@ -84,3 +86,12 @@ C_PARSE(unsigned long long, i)
|
||||
C_PARSE(float, f)
|
||||
C_PARSE(double, f)
|
||||
C_PARSE(long double, f)
|
||||
|
||||
|
||||
template <>
|
||||
int
|
||||
util::parse<int> (util::view<const char*> str)
|
||||
{
|
||||
auto intermediate = util::parse<long> (str);
|
||||
return trunc_cast<int> (intermediate);
|
||||
}
|
||||
|
12
parse.hpp
12
parse.hpp
@ -17,6 +17,8 @@
|
||||
#ifndef CRUFT_UTIL_PARSE_HPP
|
||||
#define CRUFT_UTIL_PARSE_HPP
|
||||
|
||||
#include "view.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
@ -28,16 +30,14 @@ namespace util {
|
||||
///
|
||||
/// throws std::invalid_argument when the type cannot be parsed.
|
||||
template <typename T>
|
||||
T
|
||||
parse (const char *first, const char *last);
|
||||
T parse (util::view<const char *>);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
T
|
||||
parse (const char *str)
|
||||
T parse (const char *str)
|
||||
{
|
||||
return parse<T> (str, str + strlen (str));
|
||||
return parse<T> (make_view (str));
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ namespace util {
|
||||
T
|
||||
parse (const std::string &str)
|
||||
{
|
||||
return parse<T> (std::cbegin (str), std::cend (str));
|
||||
return parse<T> (make_view (str));
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user