"Post Window" -> "Post window" prevents it being seen as two separate
[supercollider.git] / include / plugin_interface / Unroll.h
blob375844a48f9d1014f7c86cb3785ff07ea22b0cb6
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
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
23 These macros allow one to write code which can be compiled optimally depending on
24 what loop constructs the compiler can best generate code.
28 #ifndef _Unroll_
29 #define _Unroll_
31 #include <string.h>
32 #include <cassert>
34 #if 1
36 // loop type
37 #define FOR_IS_FASTER 1
38 #define WHILE_IS_FASTER 0
39 // indexing type
40 #define PREINCREMENT_IS_FASTER 1
41 #define POSTINCREMENT_IS_FASTER 0
43 #else
45 // loop type
46 #define FOR_IS_FASTER 1
47 #define WHILE_IS_FASTER 0
48 // indexing type
49 #define PREINCREMENT_IS_FASTER 0
50 #define POSTINCREMENT_IS_FASTER 1
52 #endif
55 // LOOPING MACROS :
57 #if FOR_IS_FASTER
59 #define LOOP(length, stmt) for (int xxi=0; xxi<(length); ++xxi) { stmt; }
61 #elif WHILE_IS_FASTER
63 #define LOOP(length, stmt) \
64 { int xxn = (length); \
65 while (--xxn) { \
66 stmt; \
67 } \
70 #endif
74 // above macros are not friendly to the debugger
75 #if FOR_IS_FASTER
77 #define LooP(length) for (int xxi=0; xxi<(length); ++xxi)
79 #elif WHILE_IS_FASTER
81 #define LooP(length) for (int xxi=(length); --xxi;)
83 #endif
85 /* faster loop macro, length is required to be larger than 0 */
86 #define LOOP1(length, stmt) \
87 { int xxn = (length); \
88 assert(length); \
89 do { \
90 stmt; \
91 } while (--xxn); \
95 // LOOP INDEXING :
98 meanings of the indexing macros:
99 ZXP = dereference and pre or post increment
100 ZX = dereference
101 PZ = preincrement (if applicable)
102 ZP = postincrement (if applicable)
103 ZOFF = offset from the pointer of the first element of the array
104 (preincrement requires a ZOFF of 1 which is pre-subtracted from the
105 base pointer. For other indexing types ZOFF is zero)
108 #if PREINCREMENT_IS_FASTER
109 #define ZXP(z) (*++(z))
110 #define ZX(z) (*(z))
111 #define PZ(z) (++(z))
112 #define ZP(z) (z)
113 #define ZOFF (1)
114 #elif POSTINCREMENT_IS_FASTER
115 #define ZXP(z) (*(z)++)
116 #define ZX(z) (*(z))
117 #define PZ(z) (z)
118 #define ZP(z) ((z)++)
119 #define ZOFF (0)
120 #endif
122 // ACCESSING INLETS AND OUTLETS :
124 // unit inputs
125 #define ZIN(i) (IN(i) - ZOFF) // get buffer pointer offset for iteration
126 #define ZIN0(i) (IN(i)[0]) // get first sample
128 // unit outputs
129 #define ZOUT(i) (OUT(i) - ZOFF) // get buffer pointer offset for iteration
130 #define ZOUT0(i) (OUT(i)[0]) // get first sample
132 #include "SC_BoundsMacros.h"
134 #include <assert.h>
136 // Efficiency notes: Clear and Copy was benchmarked in October 2008.
137 // See http://www.mcld.co.uk/blog/blog.php?217 and http://www.mcld.co.uk/blog/blog.php?218
139 // Set floating-point data to all zeros
140 inline void Clear(int numSamples, float *out)
142 // The memset approach is valid on any system using IEEE floating-point. On other systems, please check...
143 memset(out, 0, numSamples * sizeof(float));
146 inline void Copy(int numSamples, float *out, float *in)
148 memcpy(out, in, numSamples * sizeof(float));
151 inline void Fill(int numSamples, float *out, float level)
153 out -= ZOFF;
154 LOOP(numSamples, ZXP(out) = level; );
157 inline void Fill(int numSamples, float *out, float level, float slope)
159 out -= ZOFF;
160 LOOP(numSamples, ZXP(out) = level; level += slope; );
163 inline void Accum(int numSamples, float *out, float *in)
165 in -= ZOFF;
166 out -= ZOFF;
167 LOOP(numSamples, ZXP(out) += ZXP(in); );
170 inline void Scale(int numSamples, float *out, float level)
172 out -= ZOFF;
173 LOOP(numSamples, ZXP(out) *= level;);
176 inline float Scale(int numSamples, float *out, float level, float slope)
178 out -= ZOFF;
179 LOOP(numSamples, ZXP(out) *= level; level += slope;);
180 return level;
183 inline float Scale(int numSamples, float *out, float *in, float level, float slope)
185 in -= ZOFF;
186 out -= ZOFF;
187 LOOP(numSamples, ZXP(out) = ZXP(in) * level; level += slope;);
188 return level;
191 inline float ScaleMix(int numSamples, float *out, float *in, float level, float slope)
193 in -= ZOFF;
194 out -= ZOFF;
195 LOOP(numSamples, ZXP(out) += ZXP(in) * level; level += slope;);
196 return level;
199 inline void Scale(int numSamples, float *out, float *in, float level)
201 in -= ZOFF;
202 out -= ZOFF;
203 LOOP(numSamples, ZXP(out) = ZXP(in) * level; );
206 // in these the pointers are assumed to already have been pre-offset.
207 inline void ZCopy(int numSamples, float *out, const float *in)
209 // pointers must be 8 byte aligned
210 //assert((((long)(out+ZOFF) & 7) == 0) && (((long)(in+ZOFF) & 7) == 0));
211 if (in == out) return;
212 if ((numSamples & 1) == 0) {
213 // copying doubles is faster on powerpc.
214 double *outd = (double*)(out + ZOFF) - ZOFF;
215 double *ind = (double*)(in + ZOFF) - ZOFF;
216 LOOP(numSamples >> 1, ZXP(outd) = ZXP(ind); );
217 } else {
218 LOOP(numSamples, ZXP(out) = ZXP(in); );
222 inline void ZClear(int numSamples, float *out)
224 // pointers must be 8 byte aligned
225 //assert((((long)(out+ZOFF) & 7) == 0) && (((long)(in+ZOFF) & 7) == 0));
226 if ((numSamples & 1) == 0) {
227 // copying doubles is faster on powerpc.
228 double *outd = (double*)(out + ZOFF) - ZOFF;
229 LOOP(numSamples >> 1, ZXP(outd) = 0.; );
230 } else {
231 LOOP(numSamples, ZXP(out) = 0.f; );
235 inline void ZAccum(int numSamples, float *out, float *in)
237 LOOP(numSamples, ZXP(out) += ZXP(in); );
242 #endif