30constexpr T clamp(
const T& x,
const T& a,
const T& b)
45#if DL_PLATFORM == DL_PLATFORM_LINUX
48 return std::clamp<T>(x, 0, 1);
58 return x >= 0 && x <= 1;
68 a[1] * b[2] - a[2] * b[1],
69 a[2] * b[0] - a[0] * b[2],
70 a[0] * b[1] - a[1] * b[0] };
83 return dynamic_cast<T>(p);
90template<
typename T,
size_t N>
94 for (
int i = 0; i !=
N; ++i)
108#if DL_PLATFORM == DL_PLATFORM_WIN32
109 return std::as_const(a);
123template<
typename T,
typename V>
126 auto iter = find(container.rbegin(), container.rend(), a);
128 if (iter != container.rend())
129 container.erase(container.begin(), iter.base());
140template<PopFrontAble C,
typename F>
143 while (!container.empty())
145 auto iter = container.front();
146 container.pop_front();
241 for (
auto iter = container.begin(); iter != container.end(); ++iter)
245 for (; iter1 < container.end(); ++iter1)
251 return container.end();
259template<
typename T,
typename V>
262 if (container.size() <= per_num)
265 size_t num = (container.size() - 1) / per_num;
267 ret.resize(num + container.size());
270 auto iter = container.begin();
271 auto iter_ret = ret.begin();
272 while (iter != container.end())
274 *iter_ret++ = *iter++;
278 && i < container.size())
290template<
typename T,
typename V>
293 if (container.size() <= per_num)
296 size_t num = (container.size() - 1) / per_num;
298 ret.resize(num + container.size());
301 auto iter = container.rbegin();
302 auto iter_ret = ret.rbegin();
303 while (iter != container.rend())
305 *iter_ret++ = *iter++;
309 && i < container.size())
330template<
typename T,
typename V>
331void split(
const T& container,
V delimiter, std::vector<T>& ret)
333 if (container.empty())
337 auto iter_begin = container.begin();
342 if (*iter_begin == delimiter)
345 if (++iter_begin == container.end())
354 auto iter_find = std::find(iter_begin, container.end(), delimiter);
356 if (iter_find == container.end())
358 ret.push_back(
T(iter_begin, container.end()));
363 ret.push_back(
T(iter_begin, iter_find));
364 iter_begin = iter_find + 1;
365 if (iter_begin == container.end())
367 ret.push_back(
T(iter_begin, container.end()));
387template<
typename T,
typename V>
390 if (container.empty())
394 auto iter_begin = container.begin();
399 if (*iter_begin == delimiter)
401 if (++iter_begin == container.end())
407 auto iter_find = std::find(iter_begin, container.end(), delimiter);
409 if (iter_find == container.end())
411 ret.push_back(
T(iter_begin, container.end()));
416 ret.push_back(
T(iter_begin, iter_find));
417 iter_begin = iter_find + 1;
418 if (iter_begin == container.end())
435void split_sub(
const T& container,
const T& delimiter, std::vector<T>& ret)
437 if (container.empty())
439 assert(!delimiter.empty());
441 auto iter_pre = container.begin();
442 auto iter_d = delimiter.begin();
445 auto iter_cur = iter_pre;
447 auto iter_cat = iter_pre;
453 if (iter_cur == container.end())
455 ret.push_back(
T(iter_pre, iter_cur));
458 if (*iter_cur == *iter_d)
473 if (iter_d == delimiter.end())
475 ret.push_back(
T(iter_pre, iter_cat));
477 iter_d = delimiter.begin();
482 if (iter_cur == container.end())
484 ret.push_back(
T(iter_pre, iter_cur));
488 if (*iter_cur == *iter_d)
497 iter_d = delimiter.begin();
509template<
typename T,
typename V>
510void make_sequence(
T& c,
const std::initializer_list<std::initializer_list<V>>& vec)
512 for (
auto& iter : vec)
514 assert(iter.size() == 2);
516 const V& b = *(iter.begin() + 1);
533template<
typename C,
typename F>
536 if (container.empty())
541 auto iter_pre = std::begin(container);
542 auto iter_cur = std::next(iter_pre);
544 for (; iter_cur != std::end(container);)
546 func(*iter_pre, *iter_cur);
551 func(*iter_pre, *std::begin(container));
558template<
typename C,
typename F>
561 if (container.empty())
566 auto iter_pre = std::rbegin(container);
567 auto iter_cur = std::next(iter_pre);
569 for (; iter_cur != std::rend(container);)
571 func(*iter_pre, *iter_cur);
576 func(*iter_pre, *std::rbegin(container));
587template<IsPo
inter T,
typename FC,
typename F>
595 T node_this = s.top();
600 using C =
decltype(func_child(node_this));
601 C c = func_child(node_this);
602 for (
auto iter = c->rbegin(); iter != c->rend(); ++iter)
617 finally(
F&& func) : _func(func) {}
638template<
typename T,
size_t N>
670 static_assert(
N > 0 &&
N <= 11,
"字符串长度过长!");
672 for (
size_t i = 0; i <
N - 1; ++i)
676 if (ch >= 48 && ch <= 57)
678 else if (ch >= 65 && ch <= 90)
680 else if (ch >= 97 && ch <= 122)
687 assert(0 &&
"只能是字母、数字、下划线、点!");
689 ret |= ((uint64_t)ch << (i * 6));
类似std::array,增加xyzw、wh等成员访问
T r_insert_per_num(const T &container, V v, size_t per_num)
从后面往前,隔n个元素就插入1个值,首尾不会出现分割符
void split_no_empty(const T &container, V delimiter, std::vector< T > &ret)
以 元素 分割 容器
bool limit_bigger(Array< T, N > &a, const Array< T, N > &limit)
限制到大于某个值,如果修改了原值则返回true
void for_couple(const C &container, F func, bool ring=false)
成对遍历
void for_tree(T root, FC func_child, F func)
遍历树(使用栈,深度优先)
T cast_dynamic(void *p)
动态类型强转
void split_sub(const T &container, const T &delimiter, std::vector< T > &ret)
以 子串 分割 容器
constexpr T is_saturate(const T &x)
是否数值在[0, 1]
void for_couple_r(const C &container, F func, bool ring=false)
反向成对遍历
void make_sequence(T &c, const std::initializer_list< std::initializer_list< V > > &vec)
生成序列
void split(const T &container, V delimiter, std::vector< T > &ret)
以 元素 分割 容器
void operate_front(C &container, F func)
从容器container不断取出第一个元素,执行操作
const T & constant(T &v)
加上const修饰
constexpr Array< T, 3 > cross(const Array< T, 3 > &a, const Array< T, 3 > &b)
向量叉乘
constexpr T sign(const T &v)
返回符号,正数返回1、负数返回-1、0返回0
consteval uint64_t str_uid(const char(&str)[N])
固定条件的字符串,生成唯一id
T insert_per_num(const T &container, V v, size_t per_num)
隔n个元素就插入1个分割符,首尾不会出现分割符
constexpr T saturate(const T &x)
限制数值到 [0, 1]
constexpr T clamp(const T &x, const T &a, const T &b)
限制数值到 [a, b]
void erase_head_from_last(T &container, const V &a)
从容器container中移除 最后 匹配到的a元素 之前(包含a)的所有元素,如果没有匹配到,则什么都不做。
auto find_equal(C &container)
替换容器元素值
constexpr T & arr_last(const T(&arr)[N])
返回静态数组长度