summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/vector_ops.h
blob: bb94b0793f340b47a04b80740f776422ac2a7048 (plain) (blame)
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
143
144
145
146
147
148
149
150
151
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
 * vector_ops.h
 *
 * Base vector operations
 *
 */

#ifndef PLIB_VECTOR_OPS_H_
#define PLIB_VECTOR_OPS_H_

#include "pconfig.h"

#include <algorithm>
#include <array>
#include <type_traits>

#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#endif

namespace plib
{
	template<typename VT, typename T>
	void vec_set_scalar(const std::size_t n, VT &v, T && scalar) noexcept
	{
		const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
		for ( std::size_t i = 0; i < n; i++ )
			v[i] = s;
	}

	template<typename VT, typename VS>
	void vec_set(const std::size_t n, VT &v, const VS & source) noexcept
	{
		for ( std::size_t i = 0; i < n; i++ )
			v[i] = source[i];
	}

	template<typename T, typename V1, typename V2>
	T vec_mult(const std::size_t n, const V1 & v1, const V2 & v2 ) noexcept
	{
		using b8 = std::array<T, 8>;
		PALIGNAS_VECTOROPT() b8 value = {0};
		for (std::size_t i = 0; i < n ; i++ )
		{
			value[i & 7] += v1[i] * v2[i];
		}
		return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
	}

	template<typename T, typename VT>
	T vec_mult2(const std::size_t n, const VT &v) noexcept
	{
		using b8 = std::array<T, 8>;
		PALIGNAS_VECTOROPT() b8 value = {0};
		for (std::size_t i = 0; i < n ; i++ )
		{
			value[i & 7] += v[i] * v[i];
		}
		return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
	}

	template<typename T, typename VT>
	T vec_sum(const std::size_t n, const VT &v) noexcept
	{
		if (n<8)
		{
			T value(0);
			for (std::size_t i = 0; i < n ; i++ )
				value += v[i];

			return value;
		}
		else
		{
			using b8 = std::array<T, 8>;
			PALIGNAS_VECTOROPT() b8 value = {0};
			for (std::size_t i = 0; i < n ; i++ )
				value[i & 7] += v[i];

			return ((value[0] + value[1]) + (value[2] + value[3])) + ((value[4] + value[5]) + (value[6] + value[7]));
		}
	}

	template<typename VV, typename T, typename VR>
	void vec_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar) noexcept
	{
		const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
		for ( std::size_t i = 0; i < n; i++ )
			result[i] = s * v[i];
	}

	template<typename VR, typename VV, typename T>
	void vec_add_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar) noexcept
	{
		const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
		for ( std::size_t i = 0; i < n; i++ )
			result[i] += s * v[i];
	}

	template<typename T>
	void vec_add_mult_scalar_p(const std::size_t n, T * result, const T * v, T scalar) noexcept
	{
		for ( std::size_t i = 0; i < n; i++ )
			result[i] += scalar * v[i];
	}

	template<typename R, typename V>
	void vec_add_ip(const std::size_t n, R & result, const V & v) noexcept
	{
		for ( std::size_t i = 0; i < n; i++ )
			result[i] += v[i];
	}

	template<typename VR, typename V1, typename V2>
	void vec_sub(const std::size_t n, VR & result, const V1 &v1, const V2 & v2) noexcept
	{
		for ( std::size_t i = 0; i < n; i++ )
			result[i] = v1[i] - v2[i];
	}

	template<typename V, typename T>
	void vec_scale(const std::size_t n, V & v, T &&scalar) noexcept
	{
		const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
		for ( std::size_t i = 0; i < n; i++ )
			v[i] *= s;
	}

	template<typename T, typename V>
	T vec_maxabs(const std::size_t n, const V & v) noexcept
	{
		T ret = 0.0;
		for ( std::size_t i = 0; i < n; i++ )
			ret = std::max(ret, plib::abs(v[i]));

		return ret;
	}
} // namespace plib

#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
#pragma GCC diagnostic pop
#endif
#endif

#endif /* PLIB_VECTOR_OPS_H_ */