FFT: Prevent user from attempting hops smaller than SC's block size
[supercollider.git] / server / plugins / SIMD_Unit.hpp
blob49e4beba5b997e6b144947ef0eb23614fda86759
1 /*
2 * SuperCollider real time audio synthesis system
3 * Copyright (c) 2002 James McCartney. All rights reserved.
4 * Copyright (c) 2011 Tim Blechmann.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef SIMD_UNIT_HPP
22 #define SIMD_UNIT_HPP
24 #include "SC_PlugIn.hpp"
26 #include "simd_memory.hpp"
27 #include "simd_binary_arithmetic.hpp"
28 #include "simd_ternary_arithmetic.hpp"
29 #include "simd_mix.hpp"
31 using nova::slope_argument;
33 #if defined(__GNUC__) && !defined(__clang__)
34 #define inline_functions __attribute__ ((flatten))
35 #else
36 #define inline_functions
37 #endif
39 struct SIMD_Unit:
40 SCUnit
42 enum { scalar, unrolled, unrolled_64};
44 bool canUseSIMD (void) const
46 return (mBufLength & (nova::vec< float >::objects_per_cacheline - 1)) == 0;
49 template <int index>
50 struct ControlRateInput
52 float value;
54 void init(const SIMD_Unit * parent)
56 value = parent->in0(index);
59 bool changed(const SIMD_Unit * parent) const
61 return value != parent->in0(index);
64 #if __cplusplus <= 199711L
65 nova::detail::scalar_ramp_argument<float> slope(const SIMD_Unit * parent)
66 #else
67 decltype(nova::slope_argument(0.f, 0.f)) slope(const SIMD_Unit * parent)
68 #endif
70 float next = parent->in0(index);
71 float current = value;
72 float slope = parent->calcSlope(next, current);
73 value = next;
74 return slope_argument(current, slope);
77 operator float(void)
79 return value;
83 template <typename UnitType, void (UnitType::*UnrolledCalcFunc)(int), void (UnitType::*VectorCalcFunc)(int), void (UnitType::*ScalarCalcFunc)(int)>
84 void set_unrolled_calc_function(void)
86 if (bufferSize() == 64)
87 SCUnit::set_vector_calc_function<UnitType, UnrolledCalcFunc, ScalarCalcFunc>();
88 else
89 set_vector_calc_function<UnitType, VectorCalcFunc, ScalarCalcFunc>();
92 template <typename UnitType, void (UnitType::*VectorCalcFunc)(int), void (UnitType::*ScalarCalcFunc)(int)>
93 void set_vector_calc_function(void)
95 if (canUseSIMD())
96 SCUnit::set_vector_calc_function<UnitType, VectorCalcFunc, ScalarCalcFunc>();
97 else
98 SCUnit::set_calc_function<UnitType, ScalarCalcFunc>();
101 template <int type, typename Arg1, typename Arg2, typename Arg3>
102 static void muladd(float * out, Arg1 const & arg1, Arg2 const & arg2, Arg3 const & arg3, int inNumSamples)
104 if (type == scalar)
105 nova::muladd_vec(out, arg1, arg2, arg3, inNumSamples);
106 if (type == unrolled)
107 nova::muladd_vec_simd(out, arg1, arg2, arg3, inNumSamples);
108 if (type == unrolled_64)
109 nova::muladd_vec_simd<64>(out, arg1, arg2, arg3);
112 template <int type, typename Arg1, typename Arg2>
113 static void plus_vec(float * out, Arg1 const & arg1, Arg2 const & arg2, int inNumSamples)
115 if (type == scalar)
116 nova::plus_vec(out, arg1, arg2, inNumSamples);
117 if (type == unrolled)
118 nova::plus_vec_simd(out, arg1, arg2, inNumSamples);
119 if (type == unrolled_64)
120 nova::plus_vec_simd<64>(out, arg1, arg2);
123 template <int type, typename Arg1, typename Arg2>
124 static void times_vec(float * out, Arg1 const & arg1, Arg2 const & arg2, int inNumSamples)
126 if (type == scalar)
127 nova::times_vec(out, arg1, arg2, inNumSamples);
128 if (type == unrolled)
129 nova::times_vec_simd(out, arg1, arg2, inNumSamples);
130 if (type == unrolled_64)
131 nova::times_vec_simd<64>(out, arg1, arg2);
134 template <int type, typename Arg1, typename Arg2>
135 static void slope_vec(float * out, Arg1 const & base, Arg2 const & slope, int inNumSamples)
137 if (type == scalar)
138 nova::set_slope_vec(out, base, slope, inNumSamples);
139 else
140 nova::set_slope_vec_simd(out, base, slope, inNumSamples);
143 template <int type, typename Arg1>
144 static void slope_vec(float * out, Arg1 const & slope, int inNumSamples)
146 if (type == scalar)
147 nova::set_slope_vec(out, slope.data, slope.slope_, inNumSamples);
148 else
149 nova::set_slope_vec_simd(out, slope.data, slope.slope_, inNumSamples);
152 template <int type>
153 static void copy_vec(float * out, const float * in, int inNumSamples)
155 if (in == out)
156 return;
158 if (type == scalar)
159 nova::copyvec(out, in, inNumSamples);
160 if (type == unrolled)
161 nova::copyvec_simd(out, in, inNumSamples);
162 if (type == unrolled_64)
163 nova::copyvec_simd<64>(out, in);
166 template <int type>
167 static void set_vec(float * out, float value, int inNumSamples)
169 if (type == scalar)
170 nova::setvec(out, value, inNumSamples);
171 if (type == unrolled)
172 nova::setvec_simd(out, value, inNumSamples);
173 if (type == unrolled_64)
174 nova::setvec_simd<64>(out, value);
177 template <int type>
178 static void zero_vec(float * out, int inNumSamples)
180 if (type == scalar)
181 nova::zerovec(out, inNumSamples);
182 if (type == unrolled)
183 nova::zerovec_simd(out, inNumSamples);
184 if (type == unrolled_64)
185 nova::zerovec_simd<64>(out);
189 #endif /* SIMD_UNIT_HPP */