@@ -17,25 +17,161 @@ | |||||
// -------------------- | // -------------------- | ||||
// | // | ||||
#include <vector> | |||||
#include <string> | |||||
#include <cstring> | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
class getopt | class getopt | ||||
{ | { | ||||
public: | public: | ||||
getopt(int argc, char ** _argv); | |||||
getopt(int argc, char * const * _argv); | |||||
~getopt(); | |||||
getopt(int argc, char ** argv) | |||||
: m_argc(argc), | |||||
m_argv(argv) | |||||
{ | |||||
} | |||||
getopt(int argc, char * const * argv) | |||||
: m_argc(argc), | |||||
m_argv(argv) | |||||
{ | |||||
} | |||||
void add_opt(int short_opt, char const *long_opt, bool has_arg) | |||||
{ | |||||
optdesc o { long_opt, has_arg, nullptr, short_opt }; | |||||
m_opts.push_back(o); | |||||
/* “The standards require that the argument [to isalnum()] is either | |||||
* EOF or a value that is representable in the type unsigned char.” */ | |||||
if ((int)(unsigned char)short_opt == short_opt && isalnum(short_opt)) | |||||
{ | |||||
m_optstring += (char)short_opt; | |||||
if (has_arg) | |||||
m_optstring += ':'; | |||||
} | |||||
} | |||||
int parse() | |||||
{ | |||||
int longindex = 0; // FIXME: what is this? | |||||
/* XXX: this getopt_long implementation should not be trusted for other | |||||
* applications without any serious peer reviewing. It “just works” with | |||||
* zzuf and a few libcaca programs but may fail miserably in other | |||||
* programs. */ | |||||
char **argv = (char **)(uintptr_t)m_argv; | |||||
char *flag; | |||||
if (this->index >= m_argc) | |||||
return -1; | |||||
flag = argv[this->index]; | |||||
if (flag[0] == '-' && flag[1] != '-') | |||||
{ | |||||
char const *tmp; | |||||
int ret = flag[1]; | |||||
if (ret == '\0') | |||||
return -1; | |||||
tmp = strchr(m_optstring.c_str(), ret); | |||||
if (!tmp || ret == ':') | |||||
return '?'; | |||||
void add_opt(int short_opt, char const *long_opt, bool has_arg); | |||||
int parse(); | |||||
++this->index; | |||||
if (tmp[1] == ':') | |||||
{ | |||||
if (flag[2] != '\0') | |||||
this->arg = flag + 2; | |||||
else | |||||
{ | |||||
if (this->index >= m_argc) | |||||
goto too_few; | |||||
this->arg = argv[this->index++]; | |||||
} | |||||
return ret; | |||||
} | |||||
int index; | |||||
char *arg; | |||||
if (flag[2] != '\0') | |||||
{ | |||||
flag[1] = '-'; | |||||
--this->index; | |||||
++argv[this->index]; | |||||
} | |||||
return ret; | |||||
} | |||||
if (flag[0] == '-' && flag[1] == '-') | |||||
{ | |||||
if (flag[2] == '\0') | |||||
return -1; | |||||
for (int i = 0; m_opts[i].name; ++i) | |||||
{ | |||||
size_t l = strlen(m_opts[i].name); | |||||
if (strncmp(flag + 2, m_opts[i].name, l)) | |||||
continue; | |||||
switch (flag[2 + l]) | |||||
{ | |||||
case '=': | |||||
if (!m_opts[i].has_arg) | |||||
goto bad_opt; | |||||
longindex = i; | |||||
++this->index; | |||||
this->arg = flag + 2 + l + 1; | |||||
return m_opts[i].val; | |||||
case '\0': | |||||
longindex = i; | |||||
++this->index; | |||||
if (m_opts[i].has_arg) | |||||
{ | |||||
if (this->index >= m_argc) | |||||
goto too_few; | |||||
this->arg = argv[this->index++]; | |||||
} | |||||
return m_opts[i].val; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
bad_opt: | |||||
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); | |||||
return '?'; | |||||
too_few: | |||||
fprintf(stderr, "%s: option `%s' requires an argument\n", | |||||
argv[0], flag); | |||||
return '?'; | |||||
} | |||||
return -1; | |||||
} | |||||
int index = 1; | |||||
char *arg = nullptr; | |||||
private: | private: | ||||
std::unique_ptr<struct getopt_private> m_private; | |||||
struct optdesc | |||||
{ | |||||
char const *name; | |||||
int has_arg; | |||||
int *flag; | |||||
int val; | |||||
}; | |||||
int m_argc; | |||||
char * const *m_argv; | |||||
std::string m_optstring; | |||||
std::vector<optdesc> m_opts; | |||||
}; | }; | ||||
} | |||||
} // namespace lol | |||||
@@ -24,6 +24,7 @@ | |||||
#include <thread> | #include <thread> | ||||
#include <mutex> | #include <mutex> | ||||
#include <condition_variable> | #include <condition_variable> | ||||
#include <chrono> // std::chrono | |||||
#include <cassert> // assert() | #include <cassert> // assert() | ||||
/* XXX: workaround for a bug in Visual Studio 2012 and 2013! | /* XXX: workaround for a bug in Visual Studio 2012 and 2013! | ||||
@@ -233,5 +234,37 @@ private: | |||||
std::condition_variable m_empty_cond, m_full_cond; | std::condition_variable m_empty_cond, m_full_cond; | ||||
}; | }; | ||||
class timer | |||||
{ | |||||
public: | |||||
inline timer() { (void)get_seconds(true); } | |||||
inline void reset() { (void)get_seconds(true); } | |||||
inline float get() { return get_seconds(true); } | |||||
inline float poll() { return get_seconds(false); } | |||||
void wait(float seconds) | |||||
{ | |||||
if (seconds > 0.0f) | |||||
{ | |||||
float secs_elapsed = get_seconds(false); | |||||
std::this_thread::sleep_for(std::chrono::duration<float>(seconds - secs_elapsed)); | |||||
} | |||||
} | |||||
private: | |||||
std::chrono::steady_clock::time_point m_tp; | |||||
float get_seconds(bool do_reset) | |||||
{ | |||||
auto tp = std::chrono::steady_clock::now(), tp0 = m_tp; | |||||
if (do_reset) | |||||
m_tp = tp; | |||||
return std::chrono::duration_cast<std::chrono::duration<float>>(tp - tp0).count(); | |||||
} | |||||
}; | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -22,8 +22,9 @@ | |||||
#include <lol/base/features.h> | #include <lol/base/features.h> | ||||
#include <lol/base/core.h> | #include <lol/base/core.h> | ||||
#include <tuple> // std::tuple | |||||
#include <cassert> // assert() | |||||
#include <functional> // std::function | |||||
#include <tuple> // std::tuple | |||||
#include <cassert> // assert() | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -54,7 +55,7 @@ struct LOL_ATTR_NODISCARD polynomial | |||||
static polynomial<T> chebyshev(int n) | static polynomial<T> chebyshev(int n) | ||||
{ | { | ||||
/* Use T0(x) = 1, T1(x) = x, Tn(x) = 2 x Tn-1(x) - Tn-2(x) */ | /* Use T0(x) = 1, T1(x) = x, Tn(x) = 2 x Tn-1(x) - Tn-2(x) */ | ||||
auto coeff = [&](int i, int j) -> int64_t | |||||
std::function<int64_t (int, int)> coeff = [&](int i, int j) -> int64_t | |||||
{ | { | ||||
if (i > j || i < 0 || ((j ^ i) & 1)) | if (i > j || i < 0 || ((j ^ i) & 1)) | ||||
return (int64_t)0; | return (int64_t)0; | ||||
@@ -306,7 +307,7 @@ struct LOL_ATTR_NODISCARD polynomial | |||||
/* Add two polynomials */ | /* Add two polynomials */ | ||||
polynomial<T> &operator +=(polynomial<T> const &p) | polynomial<T> &operator +=(polynomial<T> const &p) | ||||
{ | { | ||||
int min_degree = lol::min(p.degree(), degree()); | |||||
int min_degree = std::min(p.degree(), degree()); | |||||
for (int i = 0; i <= min_degree; ++i) | for (int i = 0; i <= min_degree; ++i) | ||||
m_coefficients[i] += p[i]; | m_coefficients[i] += p[i]; | ||||
@@ -414,8 +415,8 @@ private: | |||||
/* Enforce the non-zero leading coefficient rule. */ | /* Enforce the non-zero leading coefficient rule. */ | ||||
void reduce_degree() | void reduce_degree() | ||||
{ | { | ||||
while (m_coefficients.count() && !m_coefficients.last()) | |||||
(void)m_coefficients.pop(); | |||||
while (m_coefficients.size() && !m_coefficients.back()) | |||||
m_coefficients.pop_back(); | |||||
} | } | ||||
/* The polynomial coefficients */ | /* The polynomial coefficients */ | ||||
@@ -1,20 +1,25 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
// | |||||
// Lol Engine is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#pragma once | #pragma once | ||||
// | // | ||||
// The Random number generators | // The Random number generators | ||||
// ---------------------------- | |||||
// ———————————————————————————— | |||||
// | // | ||||
#include <lol/base/features.h> | |||||
#include <cassert> | |||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
@@ -32,27 +37,29 @@ template<typename T> LOL_ATTR_NODISCARD static inline T rand(T a) | |||||
return a ? rand<T>() % a : T(0); | return a ? rand<T>() % a : T(0); | ||||
} | } | ||||
#if 0 | |||||
template<> LOL_ATTR_NODISCARD inline half rand<half>(half a) | template<> LOL_ATTR_NODISCARD inline half rand<half>(half a) | ||||
{ | { | ||||
float f = (float)std::rand() / (float)RAND_MAX; | float f = (float)std::rand() / (float)RAND_MAX; | ||||
return (half)(a * f); | return (half)(a * f); | ||||
} | } | ||||
#endif | |||||
template<> LOL_ATTR_NODISCARD inline float rand<float>(float a) | template<> LOL_ATTR_NODISCARD inline float rand<float>(float a) | ||||
{ | { | ||||
float f = (float)std::rand() / (float)RAND_MAX; | |||||
auto f = (float)std::rand() / (float)RAND_MAX; | |||||
return a * f; | return a * f; | ||||
} | } | ||||
template<> LOL_ATTR_NODISCARD inline double rand<double>(double a) | template<> LOL_ATTR_NODISCARD inline double rand<double>(double a) | ||||
{ | { | ||||
double f = (double)std::rand() / (double)RAND_MAX; | |||||
auto f = (double)std::rand() / (double)RAND_MAX; | |||||
return a * f; | return a * f; | ||||
} | } | ||||
template<> LOL_ATTR_NODISCARD inline ldouble rand<ldouble>(ldouble a) | |||||
template<> LOL_ATTR_NODISCARD inline long double rand<long double>(long double a) | |||||
{ | { | ||||
ldouble f = (ldouble)std::rand() / (ldouble)RAND_MAX; | |||||
auto f = (long double)std::rand() / (long double)RAND_MAX; | |||||
return a * f; | return a * f; | ||||
} | } | ||||
@@ -111,16 +118,17 @@ template<typename T> LOL_ATTR_NODISCARD static inline T rand() | |||||
return static_cast<T>(ret & (~(uint64_t)0 >> 1)); | return static_cast<T>(ret & (~(uint64_t)0 >> 1)); | ||||
} | } | ||||
default: | default: | ||||
ASSERT(false, "rand() doesn’t support types of size %d\n", | |||||
(int)sizeof(T)); | |||||
assert(false); | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
#if 0 | |||||
template<> LOL_ATTR_NODISCARD inline half rand<half>() { return rand<half>(1.f); } | template<> LOL_ATTR_NODISCARD inline half rand<half>() { return rand<half>(1.f); } | ||||
#endif | |||||
template<> LOL_ATTR_NODISCARD inline float rand<float>() { return rand<float>(1.f); } | template<> LOL_ATTR_NODISCARD inline float rand<float>() { return rand<float>(1.f); } | ||||
template<> LOL_ATTR_NODISCARD inline double rand<double>() { return rand<double>(1.0); } | template<> LOL_ATTR_NODISCARD inline double rand<double>() { return rand<double>(1.0); } | ||||
template<> LOL_ATTR_NODISCARD inline ldouble rand<ldouble>() { return rand<ldouble>(1.0); } | |||||
template<> LOL_ATTR_NODISCARD inline long double rand<long double>() { return rand<long double>(1.0); } | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -1,198 +0,0 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright © 2002—2018 Sam Hocevar <sam@hocevar.net> | |||||
// | |||||
// Lol Engine is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | |||||
#include <lol/engine-internal.h> | |||||
#if HAVE_GETOPT_H | |||||
# include <getopt.h> | |||||
#endif | |||||
#if HAVE_UNISTD_H | |||||
# include <unistd.h> | |||||
#endif | |||||
namespace lol | |||||
{ | |||||
struct getopt_private | |||||
{ | |||||
getopt_private(int argc, char * const * _argv) | |||||
: m_argc(argc), | |||||
m_argv(_argv) | |||||
{} | |||||
#if HAVE_GETOPT_LONG | |||||
typedef option optdesc; | |||||
#else | |||||
struct optdesc | |||||
{ | |||||
char const *name; | |||||
int has_arg; | |||||
int *flag; | |||||
int val; | |||||
}; | |||||
#endif | |||||
int m_argc; | |||||
char * const *m_argv; | |||||
std::string m_optstring; | |||||
array<optdesc> m_opts; | |||||
}; | |||||
getopt::getopt(int argc, char ** _argv) | |||||
: index(1), | |||||
arg(nullptr), | |||||
m_private(new getopt_private(argc, _argv)) | |||||
{ | |||||
} | |||||
getopt::getopt(int argc, char * const * _argv) | |||||
: index(1), | |||||
arg(nullptr), | |||||
m_private(new getopt_private(argc, _argv)) | |||||
{ | |||||
} | |||||
getopt::~getopt() | |||||
{ | |||||
} | |||||
void getopt::add_opt(int short_opt, char const *long_opt, bool has_arg) | |||||
{ | |||||
getopt_private::optdesc o { long_opt, has_arg, nullptr, short_opt }; | |||||
m_private->m_opts.push(o); | |||||
/* “The standards require that the argument [to isalnum()] is either | |||||
* EOF or a value that is representable in the type unsigned char.” */ | |||||
if ((int)(unsigned char)short_opt == short_opt && isalnum(short_opt)) | |||||
{ | |||||
m_private->m_optstring += (char)short_opt; | |||||
if (has_arg) | |||||
m_private->m_optstring += ':'; | |||||
} | |||||
} | |||||
int getopt::parse() | |||||
{ | |||||
int longindex = 0; // FIXME: what is this? | |||||
#if HAVE_GETOPT_LONG | |||||
int ret; | |||||
optind = this->index; | |||||
optarg = this->arg; | |||||
m_private->m_opts.push(getopt_private::optdesc { nullptr, 0, nullptr, 0 }); | |||||
ret = getopt_long(m_private->m_argc, m_private->m_argv, m_private->m_optstring.c_str(), | |||||
(option const *)m_private->m_opts.data(), &longindex); | |||||
this->index = optind; | |||||
this->arg = optarg; | |||||
return ret; | |||||
#else | |||||
/* XXX: this getopt_long implementation should not be trusted for other | |||||
* applications without any serious peer reviewing. It “just works” with | |||||
* zzuf and a few libcaca programs but may fail miserably in other | |||||
* programs. */ | |||||
char **argv = (char **)(uintptr_t)m_private->m_argv; | |||||
char *flag; | |||||
if (this->index >= m_private->m_argc) | |||||
return -1; | |||||
flag = argv[this->index]; | |||||
if (flag[0] == '-' && flag[1] != '-') | |||||
{ | |||||
char const *tmp; | |||||
int ret = flag[1]; | |||||
if (ret == '\0') | |||||
return -1; | |||||
tmp = strchr(m_private->m_optstring.c_str(), ret); | |||||
if (!tmp || ret == ':') | |||||
return '?'; | |||||
++this->index; | |||||
if (tmp[1] == ':') | |||||
{ | |||||
if (flag[2] != '\0') | |||||
this->arg = flag + 2; | |||||
else | |||||
{ | |||||
if (this->index >= m_private->m_argc) | |||||
goto too_few; | |||||
this->arg = argv[this->index++]; | |||||
} | |||||
return ret; | |||||
} | |||||
if (flag[2] != '\0') | |||||
{ | |||||
flag[1] = '-'; | |||||
--this->index; | |||||
++argv[this->index]; | |||||
} | |||||
return ret; | |||||
} | |||||
if (flag[0] == '-' && flag[1] == '-') | |||||
{ | |||||
if (flag[2] == '\0') | |||||
return -1; | |||||
for (int i = 0; m_private->m_opts[i].name; ++i) | |||||
{ | |||||
size_t l = strlen(m_private->m_opts[i].name); | |||||
if (strncmp(flag + 2, m_private->m_opts[i].name, l)) | |||||
continue; | |||||
switch (flag[2 + l]) | |||||
{ | |||||
case '=': | |||||
if (!m_private->m_opts[i].has_arg) | |||||
goto bad_opt; | |||||
longindex = i; | |||||
++this->index; | |||||
this->arg = flag + 2 + l + 1; | |||||
return m_private->m_opts[i].val; | |||||
case '\0': | |||||
longindex = i; | |||||
++this->index; | |||||
if (m_private->m_opts[i].has_arg) | |||||
{ | |||||
if (this->index >= m_private->m_argc) | |||||
goto too_few; | |||||
this->arg = argv[this->index++]; | |||||
} | |||||
return m_private->m_opts[i].val; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
bad_opt: | |||||
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); | |||||
return '?'; | |||||
too_few: | |||||
fprintf(stderr, "%s: option `%s' requires an argument\n", | |||||
argv[0], flag); | |||||
return '?'; | |||||
} | |||||
return -1; | |||||
#endif | |||||
} | |||||
} // namespace lol | |||||