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