Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #include <math.h>
41 : #include "cnst.h"
42 : #include "prot_fx.h"
43 : #include "rom_com.h"
44 : #include "wmc_auto.h"
45 :
46 : #ifdef _MSC_VER
47 : #pragma warning( disable : 4310 )
48 : #endif
49 :
50 : /*-----------------------------------------------------------------*
51 : * Low-complexity implementation of FFT
52 : *-----------------------------------------------------------------*/
53 :
54 : #define WMC_TOOL_SKIP
55 :
56 : #define SHC( x ) ( (Word16) x )
57 : #define FFTC( x ) WORD322WORD16( (Word32) x )
58 :
59 : #define C81_FX ( FFTC( 0x5a82799a ) ) /* FL2WORD32( 7.071067811865475e-1) */
60 : #define C82_FX ( FFTC( 0xa57d8666 ) ) /* FL2WORD32(-7.071067811865475e-1) */
61 :
62 : #define cplxMpy4_8_0( re, im, a, b, c, d ) \
63 : re = L_shr( L_sub( Mpy_32_16_1( a, c ), Mpy_32_16_1( b, d ) ), 1 ); \
64 : im = L_shr( L_add( Mpy_32_16_1( a, d ), Mpy_32_16_1( b, c ) ), 1 );
65 :
66 : #define cplxMpy4_8_1( re, im, a, b ) \
67 : re = L_shr( a, 1 ); \
68 : im = L_shr( b, 1 );
69 :
70 :
71 : /**
72 : * \brief Twiddle factors are unscaled
73 : */
74 : /*-----------------------------------------------------------------*
75 : * BASOP_fft8()
76 : *
77 : * Function performs a complex 8-point FFT
78 : * The FFT is performed inplace. The result of the FFT
79 : * is scaled by SCALEFACTOR8 bits.
80 : *
81 : * WOPS with 32x16 bit multiplications: 108 cycles
82 : *-----------------------------------------------------------------*/
83 :
84 4673448 : static void BASOP_fft8(
85 : Word32 *re,
86 : Word32 *im,
87 : Word16 s )
88 : {
89 : Word32 x00, x01, x02, x03, x04, x05, x06, x07;
90 : Word32 x08, x09, x10, x11, x12, x13, x14, x15;
91 : Word32 t00, t01, t02, t03, t04, t05, t06, t07;
92 : Word32 t08, t09, t10, t11, t12, t13, t14, t15;
93 : Word32 s00, s01, s02, s03, s04, s05, s06, s07;
94 : Word32 s08, s09, s10, s11, s12, s13, s14, s15;
95 :
96 :
97 : /* Pre-additions */
98 :
99 4673448 : x00 = L_shr( re[s * 0], SCALEFACTOR8 );
100 4673448 : x01 = L_shr( im[s * 0], SCALEFACTOR8 );
101 4673448 : x02 = L_shr( re[s * 1], SCALEFACTOR8 );
102 4673448 : x03 = L_shr( im[s * 1], SCALEFACTOR8 );
103 4673448 : x04 = L_shr( re[s * 2], SCALEFACTOR8 );
104 4673448 : x05 = L_shr( im[s * 2], SCALEFACTOR8 );
105 4673448 : x06 = L_shr( re[s * 3], SCALEFACTOR8 );
106 4673448 : x07 = L_shr( im[s * 3], SCALEFACTOR8 );
107 4673448 : x08 = L_shr( re[s * 4], SCALEFACTOR8 );
108 4673448 : x09 = L_shr( im[s * 4], SCALEFACTOR8 );
109 4673448 : x10 = L_shr( re[s * 5], SCALEFACTOR8 );
110 4673448 : x11 = L_shr( im[s * 5], SCALEFACTOR8 );
111 4673448 : x12 = L_shr( re[s * 6], SCALEFACTOR8 );
112 4673448 : x13 = L_shr( im[s * 6], SCALEFACTOR8 );
113 4673448 : x14 = L_shr( re[s * 7], SCALEFACTOR8 );
114 4673448 : x15 = L_shr( im[s * 7], SCALEFACTOR8 );
115 :
116 4673448 : t00 = L_add( x00, x08 );
117 4673448 : t02 = L_sub( x00, x08 );
118 4673448 : t01 = L_add( x01, x09 );
119 4673448 : t03 = L_sub( x01, x09 );
120 4673448 : t04 = L_add( x02, x10 );
121 4673448 : t06 = L_sub( x02, x10 );
122 4673448 : t05 = L_add( x03, x11 );
123 4673448 : t07 = L_sub( x03, x11 );
124 4673448 : t08 = L_add( x04, x12 );
125 4673448 : t10 = L_sub( x04, x12 );
126 4673448 : t09 = L_add( x05, x13 );
127 4673448 : t11 = L_sub( x05, x13 );
128 4673448 : t12 = L_add( x06, x14 );
129 4673448 : t14 = L_sub( x06, x14 );
130 4673448 : t13 = L_add( x07, x15 );
131 4673448 : t15 = L_sub( x07, x15 );
132 :
133 : /* Pre-additions and core multiplications */
134 :
135 4673448 : s00 = L_add( t00, t08 );
136 4673448 : s04 = L_sub( t00, t08 );
137 4673448 : s01 = L_add( t01, t09 );
138 4673448 : s05 = L_sub( t01, t09 );
139 4673448 : s08 = L_sub( t02, t11 );
140 4673448 : s10 = L_add( t02, t11 );
141 4673448 : s09 = L_add( t03, t10 );
142 4673448 : s11 = L_sub( t03, t10 );
143 4673448 : s02 = L_add( t04, t12 );
144 4673448 : s07 = L_sub( t04, t12 );
145 4673448 : s03 = L_add( t05, t13 );
146 4673448 : s06 = L_sub( t13, t05 );
147 :
148 4673448 : t01 = L_add( t06, t14 );
149 4673448 : t02 = L_sub( t06, t14 );
150 4673448 : t00 = L_add( t07, t15 );
151 4673448 : t03 = L_sub( t07, t15 );
152 :
153 4673448 : s12 = Mpy_32_16_1( L_add( t00, t02 ), C81_FX );
154 4673448 : s14 = Mpy_32_16_1( L_sub( t00, t02 ), C81_FX );
155 4673448 : s13 = Mpy_32_16_1( L_sub( t03, t01 ), C81_FX );
156 4673448 : s15 = Mpy_32_16_1( L_add( t01, t03 ), C82_FX );
157 :
158 : /* Post-additions */
159 :
160 4673448 : re[s * 0] = L_add( s00, s02 );
161 4673448 : move32();
162 4673448 : re[s * 4] = L_sub( s00, s02 );
163 4673448 : move32();
164 4673448 : im[s * 0] = L_add( s01, s03 );
165 4673448 : move32();
166 4673448 : im[s * 4] = L_sub( s01, s03 );
167 4673448 : move32();
168 4673448 : re[s * 2] = L_sub( s04, s06 );
169 4673448 : move32();
170 4673448 : re[s * 6] = L_add( s04, s06 );
171 4673448 : move32();
172 4673448 : im[s * 2] = L_sub( s05, s07 );
173 4673448 : move32();
174 4673448 : im[s * 6] = L_add( s05, s07 );
175 4673448 : move32();
176 4673448 : re[i_mult( s, 3 )] = L_add( s08, s14 );
177 4673448 : move32();
178 4673448 : re[i_mult( s, 7 )] = L_sub( s08, s14 );
179 4673448 : move32();
180 4673448 : im[i_mult( s, 3 )] = L_add( s09, s15 );
181 4673448 : move32();
182 4673448 : im[i_mult( s, 7 )] = L_sub( s09, s15 );
183 4673448 : move32();
184 4673448 : re[s * 1] = L_add( s10, s12 );
185 4673448 : move32();
186 4673448 : re[i_mult( s, 5 )] = L_sub( s10, s12 );
187 4673448 : move32();
188 4673448 : im[s * 1] = L_add( s11, s13 );
189 4673448 : move32();
190 4673448 : im[i_mult( s, 5 )] = L_sub( s11, s13 );
191 4673448 : move32();
192 :
193 4673448 : return;
194 : }
195 :
196 :
197 : /*-----------------------------------------------------------------*
198 : * fftN2()
199 : *
200 : * Combined FFT
201 : *-----------------------------------------------------------------*/
202 :
203 584181 : static void BASOP_fftN2(
204 : Word32 *re, /* i/o: real part */
205 : Word32 *im, /* i/o: imag part */
206 : const Word16 *W, /* i : rotation factor */
207 : Word16 dim1, /* i : length of fft1 */
208 : Word16 dim2, /* i : length of fft2 */
209 : Word16 sx, /* i : stride real and imag part */
210 : Word16 sc, /* i : stride phase rotation coefficients */
211 : Word32 *x, /* tmp: 32-bit workbuffer */
212 : Word16 Woff /* i : offset for addressing the rotation vector table */
213 : )
214 : {
215 : Word16 i, j;
216 : Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15;
217 : Word32 t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15;
218 : Word32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15;
219 :
220 5257629 : FOR( i = 0; i < dim2; i++ )
221 : {
222 42061032 : FOR( j = 0; j < dim1; j++ )
223 : {
224 37387584 : x[2 * i * dim1 + 2 * j] = re[sx * i + sx * j * dim2];
225 37387584 : move32();
226 37387584 : x[2 * i * dim1 + 2 * j + 1] = im[sx * i + sx * j * dim2];
227 37387584 : move32();
228 : }
229 : }
230 :
231 : /* dim1 == 8 */
232 5257629 : FOR( i = 0; i < dim2; i++ )
233 : {
234 4673448 : BASOP_fft8( &x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2 );
235 : }
236 :
237 : /* dim2 == 8 */
238 5257629 : FOR( i = 0; i < dim1; i++ )
239 : {
240 4673448 : cplxMpy4_8_1( x00, x01, x[2 * i + 2 * 0 * dim1], x[2 * i + 2 * 0 * dim1 + 1] );
241 :
242 4673448 : IF( i == 0 )
243 : {
244 584181 : cplxMpy4_8_1( x02, x03, x[add( shl( i, 1 ), i_mult( 2 * 1, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 1, dim1 ) ), 1 )] );
245 584181 : cplxMpy4_8_1( x04, x05, x[add( shl( i, 1 ), i_mult( 2 * 2, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 2, dim1 ) ), 1 )] );
246 584181 : cplxMpy4_8_1( x06, x07, x[add( shl( i, 1 ), i_mult( 2 * 3, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 3, dim1 ) ), 1 )] );
247 584181 : cplxMpy4_8_1( x08, x09, x[add( shl( i, 1 ), i_mult( 2 * 4, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 4, dim1 ) ), 1 )] );
248 584181 : cplxMpy4_8_1( x10, x11, x[add( shl( i, 1 ), i_mult( 2 * 5, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 5, dim1 ) ), 1 )] );
249 584181 : cplxMpy4_8_1( x12, x13, x[add( shl( i, 1 ), i_mult( 2 * 6, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 6, dim1 ) ), 1 )] );
250 584181 : cplxMpy4_8_1( x14, x15, x[add( shl( i, 1 ), i_mult( 2 * 7, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 7, dim1 ) ), 1 )] );
251 : }
252 : ELSE
253 : {
254 4089267 : cplxMpy4_8_0( x02, x03, x[add( shl( i, 1 ), i_mult( 2 * 1, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 1, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 1, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 1, dim1 ) ) ), 1 ), Woff )] );
255 4089267 : cplxMpy4_8_0( x04, x05, x[add( shl( i, 1 ), i_mult( 2 * 2, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 2, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 2, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 2, dim1 ) ) ), 1 ), Woff )] );
256 4089267 : cplxMpy4_8_0( x06, x07, x[add( shl( i, 1 ), i_mult( 2 * 3, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 3, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 3, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 3, dim1 ) ) ), 1 ), Woff )] );
257 4089267 : cplxMpy4_8_0( x08, x09, x[add( shl( i, 1 ), i_mult( 2 * 4, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 4, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 4, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 4, dim1 ) ) ), 1 ), Woff )] );
258 4089267 : cplxMpy4_8_0( x10, x11, x[add( shl( i, 1 ), i_mult( 2 * 5, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 5, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 5, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 5, dim1 ) ) ), 1 ), Woff )] );
259 4089267 : cplxMpy4_8_0( x12, x13, x[add( shl( i, 1 ), i_mult( 2 * 6, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 6, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 6, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 6, dim1 ) ) ), 1 ), Woff )] );
260 4089267 : cplxMpy4_8_0( x14, x15, x[add( shl( i, 1 ), i_mult( 2 * 7, dim1 ) )], x[add( add( shl( i, 1 ), i_mult( 2 * 7, dim1 ) ), 1 )], W[sub( add( i_mult( sc, i ), i_mult( sc, i_mult( 7, dim1 ) ) ), Woff )], W[sub( add( add( i_mult( sc, i ), i_mult( sc, i_mult( 7, dim1 ) ) ), 1 ), Woff )] );
261 : }
262 4673448 : t00 = L_shr( L_add( x00, x08 ), SCALEFACTORN2 - 1 );
263 4673448 : t02 = L_shr( L_sub( x00, x08 ), SCALEFACTORN2 - 1 );
264 4673448 : t01 = L_shr( L_add( x01, x09 ), SCALEFACTORN2 - 1 );
265 4673448 : t03 = L_shr( L_sub( x01, x09 ), SCALEFACTORN2 - 1 );
266 4673448 : t04 = L_shr( L_add( x02, x10 ), SCALEFACTORN2 - 1 );
267 4673448 : t06 = L_sub( x02, x10 );
268 4673448 : t05 = L_shr( L_add( x03, x11 ), SCALEFACTORN2 - 1 );
269 4673448 : t07 = L_sub( x03, x11 );
270 4673448 : t08 = L_shr( L_add( x04, x12 ), SCALEFACTORN2 - 1 );
271 4673448 : t10 = L_shr( L_sub( x04, x12 ), SCALEFACTORN2 - 1 );
272 4673448 : t09 = L_shr( L_add( x05, x13 ), SCALEFACTORN2 - 1 );
273 4673448 : t11 = L_shr( L_sub( x05, x13 ), SCALEFACTORN2 - 1 );
274 4673448 : t12 = L_shr( L_add( x06, x14 ), SCALEFACTORN2 - 1 );
275 4673448 : t14 = L_sub( x06, x14 );
276 4673448 : t13 = L_shr( L_add( x07, x15 ), SCALEFACTORN2 - 1 );
277 4673448 : t15 = L_sub( x07, x15 );
278 :
279 4673448 : s00 = L_add( t00, t08 );
280 4673448 : s04 = L_sub( t00, t08 );
281 4673448 : s01 = L_add( t01, t09 );
282 4673448 : s05 = L_sub( t01, t09 );
283 4673448 : s08 = L_sub( t02, t11 );
284 4673448 : s10 = L_add( t02, t11 );
285 4673448 : s09 = L_add( t03, t10 );
286 4673448 : s11 = L_sub( t03, t10 );
287 4673448 : s02 = L_add( t04, t12 );
288 4673448 : s07 = L_sub( t04, t12 );
289 4673448 : s03 = L_add( t05, t13 );
290 4673448 : s06 = L_sub( t13, t05 );
291 :
292 4673448 : t01 = L_shr( L_add( t06, t14 ), SCALEFACTORN2 - 1 );
293 4673448 : t02 = L_shr( L_sub( t06, t14 ), SCALEFACTORN2 - 1 );
294 4673448 : t00 = L_shr( L_add( t07, t15 ), SCALEFACTORN2 - 1 );
295 4673448 : t03 = L_shr( L_sub( t07, t15 ), SCALEFACTORN2 - 1 );
296 :
297 4673448 : s12 = Mpy_32_16_1( L_add( t00, t02 ), C81_FX );
298 4673448 : s14 = Mpy_32_16_1( L_sub( t00, t02 ), C81_FX );
299 4673448 : s13 = Mpy_32_16_1( L_sub( t03, t01 ), C81_FX );
300 4673448 : s15 = Mpy_32_16_1( L_add( t01, t03 ), C82_FX );
301 :
302 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 0, dim1 ) ) )] = L_add( s00, s02 );
303 4673448 : move32();
304 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 0, dim1 ) ) )] = L_add( s01, s03 );
305 4673448 : move32();
306 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 1, dim1 ) ) )] = L_add( s10, s12 );
307 4673448 : move32();
308 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 1, dim1 ) ) )] = L_add( s11, s13 );
309 4673448 : move32();
310 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 2, dim1 ) ) )] = L_sub( s04, s06 );
311 4673448 : move32();
312 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 2, dim1 ) ) )] = L_sub( s05, s07 );
313 4673448 : move32();
314 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 3, dim1 ) ) )] = L_add( s08, s14 );
315 4673448 : move32();
316 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 3, dim1 ) ) )] = L_add( s09, s15 );
317 4673448 : move32();
318 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 4, dim1 ) ) )] = L_sub( s00, s02 );
319 4673448 : move32();
320 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 4, dim1 ) ) )] = L_sub( s01, s03 );
321 4673448 : move32();
322 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 5, dim1 ) ) )] = L_sub( s10, s12 );
323 4673448 : move32();
324 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 5, dim1 ) ) )] = L_sub( s11, s13 );
325 4673448 : move32();
326 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 6, dim1 ) ) )] = L_add( s04, s06 );
327 4673448 : move32();
328 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 6, dim1 ) ) )] = L_add( s05, s07 );
329 4673448 : move32();
330 4673448 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 7, dim1 ) ) )] = L_sub( s08, s14 );
331 4673448 : move32();
332 4673448 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 7, dim1 ) ) )] = L_sub( s09, s15 );
333 4673448 : move32();
334 : }
335 :
336 584181 : return;
337 : }
338 :
339 :
340 : /*-----------------------------------------------------------------*
341 : * BASOP_cfft_ivas()
342 : *
343 : * Complex valued FFT
344 : *-----------------------------------------------------------------*/
345 :
346 584181 : void BASOP_cfft_ivas(
347 : Word32 *re, /* i/o: real part */
348 : Word32 *im, /* i/o: imag part */
349 : Word16 s, /* i : stride real and imag part */
350 : Word16 *scale /* i : scalefactor */
351 : )
352 : {
353 : Word32 x[2 * 64];
354 :
355 : /* FFT for len = FDNS_NPTS */
356 584181 : BASOP_fftN2( re, im, RotVector_256, 8, 8, s, 8, x, 64 );
357 584181 : s = add( *scale, SCALEFACTOR64 );
358 :
359 584181 : *scale = s;
360 584181 : move16();
361 :
362 584181 : return;
363 : }
364 :
365 :
366 : #undef WMC_TOOL_SKIP
|