dl
dl_algorithm.h
浏览该文件的文档.
1
12#pragma once
13
14#include <algorithm>
15#include <cassert>
16#include <stack>
17#include <array>
18#include <vector>
19
20#include "base/dl_concept.h"
21#include "base/dl_array.h"
22
23namespace dl
24{
25
29template<typename T>
30constexpr T clamp(const T& x, const T& a, const T& b)
31{
32 if (x < a)
33 return a;
34 if (b < a)
35 return b;
36 return x;
37}
38
42template<typename T>
43constexpr T saturate(const T& x)
44{
45#if DL_PLATFORM == DL_PLATFORM_LINUX
46 return dl::clamp<T>(x, 0, 1);
47#else
48 return std::clamp<T>(x, 0, 1);
49#endif
50}
51
55template<typename T>
56constexpr T is_saturate(const T& x)
57{
58 return x >= 0 && x <= 1;
59}
60
64template<typename T>
65constexpr Array<T, 3> cross(const Array<T, 3>& a, const Array<T, 3>& b)
66{
67 return {
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] };
71}
72
73
74
79template<typename T>
80[[deprecated]]
81inline T cast_dynamic(void* p)
82{
83 return dynamic_cast<T>(p);
84}
85
86
90template<typename T, size_t N>
91bool limit_bigger(Array<T, N>& a, const Array<T, N>& limit)
92{
93 bool ret = false;
94 for (int i = 0; i != N; ++i)
95 {
96 if (a[i] < limit[i])
97 {
98 a[i] = limit[i];
99 ret = true;
100 }
101 }
102 return ret;
103}
104
105template <typename T>
106inline const T& as_const(T& a)
107{
108#if DL_PLATFORM == DL_PLATFORM_WIN32
109 return std::as_const(a);
110#else
111 return (const T&)a;
112#endif
113}
114
115//-------------------------------------------------------other-----------------------------------------
116
123template<typename T, typename V>
124void erase_head_from_last(T& container, const V& a)
125{
126 auto iter = find(container.rbegin(), container.rend(), a);
127
128 if (iter != container.rend())
129 container.erase(container.begin(), iter.base());
130}
131
132
133
140template<PopFrontAble C, typename F>
141void operate_front(C& container, F func)
142{
143 while (!container.empty())
144 {
145 auto iter = container.front();
146 container.pop_front();
147
148 func(iter);
149 }
150}
151
152
153
154
156//namespace Find
157//{
158// /**
159// * @brief find,返回下标
160// * @note 失败返回-1
161// */
162// template<typename T, typename V>
163// size_t Index(const T& container, const V& v)
164// {
165// size_t size = container.size();
166// for (size_t i = 0; i < size; ++i)
167// {
168// if (container[i] == v)
169// {
170// return i;
171// }
172// }
173// return -1;
174// }
175// /**
176// * @brief find,返回下标
177// * @note 失败返回y == size
178// */
179// template<typename T, typename V>
180// array<size_t, 2> Index(const vector<vector<T>>& container, const V& v)
181// {
182// array<size_t, 2> ret{};
183// for (; ret[1] < container.size(); ++ret[1])
184// {
185// auto& line = container[ret[1]];
186// for (ret[0] = 0; ret[0] < line.size(); ++ret[0])
187// {
188// if (line[ret[0]] == v)
189// {
190// return ret;
191// }
192// }
193// }
194// return ret;
195// }
196//}
197
198
199
200
205template<typename T>
206inline T* pointer(T&& x)
207{
208 return &x;
209}
210
214template<typename T>
215inline const T& constant(T& v)
216{
217 return v;
218}
219
220
221
225//template<typename T, typename V>
226//inline void replace(T& vec, V v, V v_new)
227//{
228// for (auto& iter : vec)
229// {
230// if (iter == v)
231// iter = v_new;
232// }
233//}
234
238template<typename C>
239auto find_equal(C& container)
240{
241 for (auto iter = container.begin(); iter != container.end(); ++iter)
242 {
243 auto iter1 = iter;
244 ++iter1;
245 for (; iter1 < container.end(); ++iter1)
246 {
247 if (*iter == *iter1)
248 return iter1;
249 }
250 }
251 return container.end();
252}
253
254
259template<typename T, typename V>
260T insert_per_num(const T& container, V v, size_t per_num)
261{
262 if (container.size() <= per_num)
263 return T(container);
264
265 size_t num = (container.size() - 1) / per_num;//每3个插入计算得出:9 -> 2; 11 -> 3
266 T ret;
267 ret.resize(num + container.size());
268
269 size_t i = 0;
270 auto iter = container.begin();
271 auto iter_ret = ret.begin();
272 while (iter != container.end())
273 {
274 *iter_ret++ = *iter++;
275 ++i;
276 //满per_num额外加入一个v,且不为最后一个
277 if (i % per_num == 0
278 && i < container.size())
279 *iter_ret++ = v;
280 }
281
282 return ret;
283}
284
285
290template<typename T, typename V>
291T r_insert_per_num(const T& container, V v, size_t per_num)
292{
293 if (container.size() <= per_num)
294 return T(container);
295
296 size_t num = (container.size() - 1) / per_num;//每3个插入计算得出:9 -> 2; 11 -> 3
297 T ret;
298 ret.resize(num + container.size());
299
300 size_t i = 0;
301 auto iter = container.rbegin();
302 auto iter_ret = ret.rbegin();
303 while (iter != container.rend())
304 {
305 *iter_ret++ = *iter++;
306 ++i;
307 //满per_num额外加入一个v,且不为最后一个
308 if (i % per_num == 0
309 && i < container.size())
310 *iter_ret++ = v;
311 }
312
313 return ret;
314}
315
330template<typename T, typename V>
331void split(const T& container, V delimiter, std::vector<T>& ret)
332{
333 if (container.empty())
334 return;
335
336 //主迭代器位置
337 auto iter_begin = container.begin();
338
339 while (true)
340 {
341 //当前位置就是分隔符,则添加 空元素
342 if (*iter_begin == delimiter)
343 {
344 ret.push_back(T());
345 if (++iter_begin == container.end())
346 {
347 ret.push_back(T());//还要额外添加一个
348 return;
349 }
350 }
351 else
352 {
353 //分隔符位置
354 auto iter_find = std::find(iter_begin, container.end(), delimiter);
355
356 if (iter_find == container.end())
357 {//分隔符 未找到(说明字符串读完了,最后没有分隔符的情况)
358 ret.push_back(T(iter_begin, container.end()));
359 return;
360 }
361 else
362 {
363 ret.push_back(T(iter_begin, iter_find));
364 iter_begin = iter_find + 1;
365 if (iter_begin == container.end())
366 {
367 ret.push_back(T(iter_begin, container.end()));
368 return;
369 }
370 }
371 }
372 }
373}
374
387template<typename T, typename V>
388void split_no_empty(const T& container, V delimiter, std::vector<T>& ret)
389{
390 if (container.empty())
391 return;
392
393 //主迭代器位置
394 auto iter_begin = container.begin();
395
396 while (true)
397 {
398 //当前位置就是分隔符,不添加 空元素,只往后移动
399 if (*iter_begin == delimiter)
400 {
401 if (++iter_begin == container.end())
402 return;
403 }
404 else
405 {
406 //分隔符位置
407 auto iter_find = std::find(iter_begin, container.end(), delimiter);
408
409 if (iter_find == container.end())
410 {//分隔符 未找到(说明字符串读完了,最后没有分隔符的情况)
411 ret.push_back(T(iter_begin, container.end()));
412 return;
413 }
414 else
415 {
416 ret.push_back(T(iter_begin, iter_find));
417 iter_begin = iter_find + 1;
418 if (iter_begin == container.end())
419 return;
420 }
421 }
422 }
423}
424
434template<typename T>
435void split_sub(const T& container, const T& delimiter, std::vector<T>& ret)
436{
437 if (container.empty())
438 return;
439 assert(!delimiter.empty());
440
441 auto iter_pre = container.begin();
442 auto iter_d = delimiter.begin();
443
444 bool mode_d = false;//是否匹配分隔符中
445 auto iter_cur = iter_pre;
446
447 auto iter_cat = iter_pre;//开始匹配分隔符的位置
448
449 while (true)
450 {
451 if (!mode_d)
452 {//正常模式
453 if (iter_cur == container.end())
454 {
455 ret.push_back(T(iter_pre, iter_cur));
456 return;
457 }
458 if (*iter_cur == *iter_d)
459 { // 匹配到分隔符首个,进入匹配模式
460 mode_d = true;
461 iter_cat = iter_cur;
462 ++iter_cur;
463 ++iter_d;
464 continue;
465 }
466 else
467 {
468 ++iter_cur;
469 }
470 }
471 else
472 {//匹配模式
473 if (iter_d == delimiter.end())
474 {//完全匹配分隔符
475 ret.push_back(T(iter_pre, iter_cat));
476 mode_d = false;
477 iter_d = delimiter.begin();
478 iter_pre = iter_cur;
479 continue;
480 }
481
482 if (iter_cur == container.end())
483 {//字符结束,未完全匹配
484 ret.push_back(T(iter_pre, iter_cur));
485 return;
486 }
487
488 if (*iter_cur == *iter_d)
489 {//当前匹配
490 ++iter_cur;
491 ++iter_d;
492 continue;
493 }
494 else
495 {//不匹配,进入普通模式
496 mode_d = false;
497 iter_d = delimiter.begin();
498 continue;
499 }
500 }
501 }
502}
503
509template<typename T, typename V>
510void make_sequence(T& c, const std::initializer_list<std::initializer_list<V>>& vec)
511{
512 for (auto& iter : vec)
513 {
514 assert(iter.size() == 2);
515 V f = *iter.begin();
516 const V& b = *(iter.begin() + 1);
517 assert(f < b);
518 while (f < b)
519 {
520 c.push_back(f++);
521 }
522 }
523}
524
533template<typename C, typename F>
534void for_couple(const C& container, F func, bool ring = false)
535{
536 if (container.empty())
537 {
538 return;
539 }
540
541 auto iter_pre = std::begin(container);
542 auto iter_cur = std::next(iter_pre);
543
544 for (; iter_cur != std::end(container);)
545 {
546 func(*iter_pre, *iter_cur);
547 ++iter_pre;
548 ++iter_cur;
549 }
550 if (ring)
551 func(*iter_pre, *std::begin(container));
552}
553
558template<typename C, typename F>
559void for_couple_r(const C& container, F func, bool ring = false)
560{
561 if (container.empty())
562 {
563 return;
564 }
565
566 auto iter_pre = std::rbegin(container);
567 auto iter_cur = std::next(iter_pre);
568
569 for (; iter_cur != std::rend(container);)
570 {
571 func(*iter_pre, *iter_cur);
572 ++iter_pre;
573 ++iter_cur;
574 }
575 if (ring)
576 func(*iter_pre, *std::rbegin(container));
577}
578
587template<IsPointer T, typename FC, typename F>
588void for_tree(T root, FC func_child, F func)
589{
590 std::stack<T> s;
591 s.push(root);
592
593 while (!s.empty())
594 {
595 T node_this = s.top();
596 s.pop();
597 func(node_this);
598
599 //反向添加,这样左子树先遍历
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)
603 {
604 T& node = *iter;
605 s.push(node);
606 }
607 }
608}
609
613template<typename F>
615{
616public:
617 finally(F&& func) : _func(func) {}
618 ~finally() { _func(); }
619private:
620 F _func;
621};
622
627/*template<typename T, size_t N>
628[[deprecated]]
629constexpr size_t arr_size(const T(&)[N])
630{
631 return N;
632}*/
633
634
638template<typename T, size_t N>
639constexpr T& arr_last(const T(&arr)[N])
640{
641 return arr[N - 1];
642}
643
647template<IsSigned T>
648constexpr T sign(const T& v)
649{
650 if (v > 0)
651 return 1;
652 else if (v < 0)
653 return -1;
654 else
655 return 0;
656}
657
658
666template<size_t N>
667consteval uint64_t str_uid(const char(&str)[N])
668{
669 //64 / 6 = 10 再加1结束符
670 static_assert(N > 0 && N <= 11, "字符串长度过长!");
671 uint64_t ret = 0;
672 for (size_t i = 0; i < N - 1; ++i)
673 {
674 char ch = str[i];
675
676 if (ch >= 48 && ch <= 57)
677 ch += 6;//0-9
678 else if (ch >= 65 && ch <= 90)
679 ch -= 65;//A-Z
680 else if (ch >= 97 && ch <= 122)
681 ch -= 71;//a-z
682 else if (ch == 95)
683 ch = 62;
684 else if (ch == 46)
685 ch = 63;
686 else
687 assert(0 && "只能是字母、数字、下划线、点!");
688
689 ret |= ((uint64_t)ch << (i * 6));
690 }
691 return ret;
692}
693}
类似std::array,增加xyzw、wh等成员访问
用于模板限定,更好的报错信息
T r_insert_per_num(const T &container, V v, size_t per_num)
从后面往前,隔n个元素就插入1个值,首尾不会出现分割符
T * pointer(T &&x)
查找算法
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]
const T & as_const(T &a)
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])
返回静态数组长度