-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.h
142 lines (130 loc) · 3.57 KB
/
util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// =======================================================================
// Copyright (c) 2016-2020 by LI YANZHE. All rights reserved.
// Author: LI YANZHE <[email protected]>
// Created by LI YANZHE on 5/1/19.
// =======================================================================
#ifndef IMPROCLAB_UTIL_H
#define IMPROCLAB_UTIL_H
#include <random>
#include <iostream>
#include <array>
//#define IDX_2D(i, j, WIDTH) ((i) * WIDTH + (j))
//#define IDX_3D(i, j, k, WIDTH, DEPTH) (IDX(i, j, WIDTH) * DEPTH + k)
#define MIN(x, y) ((x) <= (y) ? (x) : (y))
#define MAX(x, y) ((x) >= (y) ? (x) : (y))
#define IS_ZERO(x) (std::fabs(x) <= std::numeric_limits<float>::epsilon())
#define F_EQUAL(x, y) IS_ZERO((x)-(y))
#define ROUND_TO_ZERO(x) (IS_ZERO(x) ? 0 : (x))
#define PI (3.1415925635)
//#define ROUND(x) (int) ((x) + 0.5)
#define ROUND(x) (std::lround(x))
namespace lyz {
/**
* 用0填充目标序列
* @param dst 目标序列
* @param n 序列长度
*/
template<typename T>
inline void zero_fill(T *dst, int n) { for (int i = 0; i < n; ++i) dst[i] = 0; }
/**
* 获取数组的最大值和最小值
* @param src
* @param n
* @param min 输出最小值, 需要事先赋初值
* @param max 输出最大值, 需要事先赋初值
*/
template<typename T>
inline void min_max(const T *src, int n, T *min, T *max) {
for (int i = 0; i < n; ++i) {
T val = src[i];
*min = val <= *min ? val : *min;
*max = val > *max ? val : *max;
}
}
/**
* 计算src数组中元素值与x的绝对值最小的元素的索引值, 如果有多个匹配, 取最小索引
* @tparam T
* @param x 待比较元素
* @param src 数组
* @param n 数组长度
* @return 最小匹配索引
*/
template<typename T>
inline int argmin_abs(T x, const T *src, int n) {
T min = std::numeric_limits<T>::max();
int idx = 0;
for (int i = 0; i < n; ++i) {
T abs = std::fabs(src[i] - x);
if (abs < min) {
min = abs;
idx = i;
}
}
return idx;
}
/**
* 序列乘以标量
* @param src 输入序列
* @param dst 输出序列
* @param factor 乘法因子
* @param n 序列长度
*/
template<typename T1, typename T2>
inline void scalar_mul(const T1 *src, T2 *dst, double factor, int n) {
for (int i = 0; i < n; ++i)
dst[i] = src[i] * factor;
}
/**
* 分配二维内存
* @param m 行数
* @param n 列数
* @return 分配后的二级指针
*/
template<typename T>
inline T **alloc_2d(int m, int n) {
T **mat = new T *[m];
for (int i = 0; i < m; ++i)
mat[i] = new T[n];
return mat;
}
/**
* 释放二级指针
* @param mat 目标二级指针
* @param m 行数
*/
template<typename T>
inline void delete_2d(T **mat, int m) {
for (int i = 0; i < m; ++i)
delete[] mat[i];
delete[] mat;
}
template<typename T>
inline void print_mat(const T *src, int n) {
for (int i = 0; i < n; ++i)
std::cout << (float) src[i] << "\t";
std::cout << std::endl;
}
/**
* 多维索引转一维索引
* 使用方法:
* 对于2维mxn矩阵, 访问i,j 元素, 使用 IDX(i,j,n)
* 对于n维形状为(s1,s2,...,sn)的矩阵, 访问第(e1,e2,...,en)位置的元素, 使用IDX(e1,e2,...,en,s2,s3,...,sn)
* @param params
* @return 一维索引
*/
template<typename ...Args>
inline constexpr size_t IDX(const Args... params) {
constexpr size_t N = sizeof...(Args);
constexpr size_t NDIMS = N / 2 + 1;
std::array<int, N> args{params...};
auto ibegin = args.begin();
auto sbegin = ibegin + NDIMS;
size_t res = 0;
for (int dim = 0; dim < NDIMS; ++dim) {
size_t factor = dim > 0 ? sbegin[dim - 1] : 0;
res = res * factor + ibegin[dim];
}
return res;
}
}
#endif //IMPROCLAB_UTIL_H