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 1952728 : 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 1952728 : x00 = L_shr( re[s * 0], SCALEFACTOR8 );
100 1952728 : x01 = L_shr( im[s * 0], SCALEFACTOR8 );
101 1952728 : x02 = L_shr( re[s * 1], SCALEFACTOR8 );
102 1952728 : x03 = L_shr( im[s * 1], SCALEFACTOR8 );
103 1952728 : x04 = L_shr( re[s * 2], SCALEFACTOR8 );
104 1952728 : x05 = L_shr( im[s * 2], SCALEFACTOR8 );
105 1952728 : x06 = L_shr( re[s * 3], SCALEFACTOR8 );
106 1952728 : x07 = L_shr( im[s * 3], SCALEFACTOR8 );
107 1952728 : x08 = L_shr( re[s * 4], SCALEFACTOR8 );
108 1952728 : x09 = L_shr( im[s * 4], SCALEFACTOR8 );
109 1952728 : x10 = L_shr( re[s * 5], SCALEFACTOR8 );
110 1952728 : x11 = L_shr( im[s * 5], SCALEFACTOR8 );
111 1952728 : x12 = L_shr( re[s * 6], SCALEFACTOR8 );
112 1952728 : x13 = L_shr( im[s * 6], SCALEFACTOR8 );
113 1952728 : x14 = L_shr( re[s * 7], SCALEFACTOR8 );
114 1952728 : x15 = L_shr( im[s * 7], SCALEFACTOR8 );
115 :
116 1952728 : t00 = L_add( x00, x08 );
117 1952728 : t02 = L_sub( x00, x08 );
118 1952728 : t01 = L_add( x01, x09 );
119 1952728 : t03 = L_sub( x01, x09 );
120 1952728 : t04 = L_add( x02, x10 );
121 1952728 : t06 = L_sub( x02, x10 );
122 1952728 : t05 = L_add( x03, x11 );
123 1952728 : t07 = L_sub( x03, x11 );
124 1952728 : t08 = L_add( x04, x12 );
125 1952728 : t10 = L_sub( x04, x12 );
126 1952728 : t09 = L_add( x05, x13 );
127 1952728 : t11 = L_sub( x05, x13 );
128 1952728 : t12 = L_add( x06, x14 );
129 1952728 : t14 = L_sub( x06, x14 );
130 1952728 : t13 = L_add( x07, x15 );
131 1952728 : t15 = L_sub( x07, x15 );
132 :
133 : /* Pre-additions and core multiplications */
134 :
135 1952728 : s00 = L_add( t00, t08 );
136 1952728 : s04 = L_sub( t00, t08 );
137 1952728 : s01 = L_add( t01, t09 );
138 1952728 : s05 = L_sub( t01, t09 );
139 1952728 : s08 = L_sub( t02, t11 );
140 1952728 : s10 = L_add( t02, t11 );
141 1952728 : s09 = L_add( t03, t10 );
142 1952728 : s11 = L_sub( t03, t10 );
143 1952728 : s02 = L_add( t04, t12 );
144 1952728 : s07 = L_sub( t04, t12 );
145 1952728 : s03 = L_add( t05, t13 );
146 1952728 : s06 = L_sub( t13, t05 );
147 :
148 1952728 : t01 = L_add( t06, t14 );
149 1952728 : t02 = L_sub( t06, t14 );
150 1952728 : t00 = L_add( t07, t15 );
151 1952728 : t03 = L_sub( t07, t15 );
152 :
153 1952728 : s12 = Mpy_32_16_1( L_add( t00, t02 ), C81_FX );
154 1952728 : s14 = Mpy_32_16_1( L_sub( t00, t02 ), C81_FX );
155 1952728 : s13 = Mpy_32_16_1( L_sub( t03, t01 ), C81_FX );
156 1952728 : s15 = Mpy_32_16_1( L_add( t01, t03 ), C82_FX );
157 :
158 : /* Post-additions */
159 :
160 1952728 : re[s * 0] = L_add( s00, s02 );
161 1952728 : move32();
162 1952728 : re[s * 4] = L_sub( s00, s02 );
163 1952728 : move32();
164 1952728 : im[s * 0] = L_add( s01, s03 );
165 1952728 : move32();
166 1952728 : im[s * 4] = L_sub( s01, s03 );
167 1952728 : move32();
168 1952728 : re[s * 2] = L_sub( s04, s06 );
169 1952728 : move32();
170 1952728 : re[s * 6] = L_add( s04, s06 );
171 1952728 : move32();
172 1952728 : im[s * 2] = L_sub( s05, s07 );
173 1952728 : move32();
174 1952728 : im[s * 6] = L_add( s05, s07 );
175 1952728 : move32();
176 1952728 : re[i_mult( s, 3 )] = L_add( s08, s14 );
177 1952728 : move32();
178 1952728 : re[i_mult( s, 7 )] = L_sub( s08, s14 );
179 1952728 : move32();
180 1952728 : im[i_mult( s, 3 )] = L_add( s09, s15 );
181 1952728 : move32();
182 1952728 : im[i_mult( s, 7 )] = L_sub( s09, s15 );
183 1952728 : move32();
184 1952728 : re[s * 1] = L_add( s10, s12 );
185 1952728 : move32();
186 1952728 : re[i_mult( s, 5 )] = L_sub( s10, s12 );
187 1952728 : move32();
188 1952728 : im[s * 1] = L_add( s11, s13 );
189 1952728 : move32();
190 1952728 : im[i_mult( s, 5 )] = L_sub( s11, s13 );
191 1952728 : move32();
192 :
193 1952728 : return;
194 : }
195 :
196 :
197 : /*-----------------------------------------------------------------*
198 : * fftN2()
199 : *
200 : * Combined FFT
201 : *-----------------------------------------------------------------*/
202 :
203 244091 : 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 2196819 : FOR( i = 0; i < dim2; i++ )
221 : {
222 17574552 : FOR( j = 0; j < dim1; j++ )
223 : {
224 15621824 : x[2 * i * dim1 + 2 * j] = re[sx * i + sx * j * dim2];
225 15621824 : move32();
226 15621824 : x[2 * i * dim1 + 2 * j + 1] = im[sx * i + sx * j * dim2];
227 15621824 : move32();
228 : }
229 : }
230 :
231 : /* dim1 == 8 */
232 2196819 : FOR( i = 0; i < dim2; i++ )
233 : {
234 1952728 : BASOP_fft8( &x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2 );
235 : }
236 :
237 : /* dim2 == 8 */
238 2196819 : FOR( i = 0; i < dim1; i++ )
239 : {
240 1952728 : cplxMpy4_8_1( x00, x01, x[2 * i + 2 * 0 * dim1], x[2 * i + 2 * 0 * dim1 + 1] );
241 :
242 1952728 : IF( i == 0 )
243 : {
244 244091 : 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 244091 : 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 244091 : 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 244091 : 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 244091 : 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 244091 : 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 244091 : 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 1708637 : 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 1708637 : 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 1708637 : 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 1708637 : 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 1708637 : 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 1708637 : 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 1708637 : 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 1952728 : t00 = L_shr( L_add( x00, x08 ), SCALEFACTORN2 - 1 );
263 1952728 : t02 = L_shr( L_sub( x00, x08 ), SCALEFACTORN2 - 1 );
264 1952728 : t01 = L_shr( L_add( x01, x09 ), SCALEFACTORN2 - 1 );
265 1952728 : t03 = L_shr( L_sub( x01, x09 ), SCALEFACTORN2 - 1 );
266 1952728 : t04 = L_shr( L_add( x02, x10 ), SCALEFACTORN2 - 1 );
267 1952728 : t06 = L_sub( x02, x10 );
268 1952728 : t05 = L_shr( L_add( x03, x11 ), SCALEFACTORN2 - 1 );
269 1952728 : t07 = L_sub( x03, x11 );
270 1952728 : t08 = L_shr( L_add( x04, x12 ), SCALEFACTORN2 - 1 );
271 1952728 : t10 = L_shr( L_sub( x04, x12 ), SCALEFACTORN2 - 1 );
272 1952728 : t09 = L_shr( L_add( x05, x13 ), SCALEFACTORN2 - 1 );
273 1952728 : t11 = L_shr( L_sub( x05, x13 ), SCALEFACTORN2 - 1 );
274 1952728 : t12 = L_shr( L_add( x06, x14 ), SCALEFACTORN2 - 1 );
275 1952728 : t14 = L_sub( x06, x14 );
276 1952728 : t13 = L_shr( L_add( x07, x15 ), SCALEFACTORN2 - 1 );
277 1952728 : t15 = L_sub( x07, x15 );
278 :
279 1952728 : s00 = L_add( t00, t08 );
280 1952728 : s04 = L_sub( t00, t08 );
281 1952728 : s01 = L_add( t01, t09 );
282 1952728 : s05 = L_sub( t01, t09 );
283 1952728 : s08 = L_sub( t02, t11 );
284 1952728 : s10 = L_add( t02, t11 );
285 1952728 : s09 = L_add( t03, t10 );
286 1952728 : s11 = L_sub( t03, t10 );
287 1952728 : s02 = L_add( t04, t12 );
288 1952728 : s07 = L_sub( t04, t12 );
289 1952728 : s03 = L_add( t05, t13 );
290 1952728 : s06 = L_sub( t13, t05 );
291 :
292 1952728 : t01 = L_shr( L_add( t06, t14 ), SCALEFACTORN2 - 1 );
293 1952728 : t02 = L_shr( L_sub( t06, t14 ), SCALEFACTORN2 - 1 );
294 1952728 : t00 = L_shr( L_add( t07, t15 ), SCALEFACTORN2 - 1 );
295 1952728 : t03 = L_shr( L_sub( t07, t15 ), SCALEFACTORN2 - 1 );
296 :
297 1952728 : s12 = Mpy_32_16_1( L_add( t00, t02 ), C81_FX );
298 1952728 : s14 = Mpy_32_16_1( L_sub( t00, t02 ), C81_FX );
299 1952728 : s13 = Mpy_32_16_1( L_sub( t03, t01 ), C81_FX );
300 1952728 : s15 = Mpy_32_16_1( L_add( t01, t03 ), C82_FX );
301 :
302 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 0, dim1 ) ) )] = L_add( s00, s02 );
303 1952728 : move32();
304 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 0, dim1 ) ) )] = L_add( s01, s03 );
305 1952728 : move32();
306 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 1, dim1 ) ) )] = L_add( s10, s12 );
307 1952728 : move32();
308 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 1, dim1 ) ) )] = L_add( s11, s13 );
309 1952728 : move32();
310 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 2, dim1 ) ) )] = L_sub( s04, s06 );
311 1952728 : move32();
312 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 2, dim1 ) ) )] = L_sub( s05, s07 );
313 1952728 : move32();
314 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 3, dim1 ) ) )] = L_add( s08, s14 );
315 1952728 : move32();
316 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 3, dim1 ) ) )] = L_add( s09, s15 );
317 1952728 : move32();
318 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 4, dim1 ) ) )] = L_sub( s00, s02 );
319 1952728 : move32();
320 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 4, dim1 ) ) )] = L_sub( s01, s03 );
321 1952728 : move32();
322 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 5, dim1 ) ) )] = L_sub( s10, s12 );
323 1952728 : move32();
324 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 5, dim1 ) ) )] = L_sub( s11, s13 );
325 1952728 : move32();
326 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 6, dim1 ) ) )] = L_add( s04, s06 );
327 1952728 : move32();
328 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 6, dim1 ) ) )] = L_add( s05, s07 );
329 1952728 : move32();
330 1952728 : re[add( i_mult( sx, i ), i_mult( sx, i_mult( 7, dim1 ) ) )] = L_sub( s08, s14 );
331 1952728 : move32();
332 1952728 : im[add( i_mult( sx, i ), i_mult( sx, i_mult( 7, dim1 ) ) )] = L_sub( s09, s15 );
333 1952728 : move32();
334 : }
335 :
336 244091 : return;
337 : }
338 :
339 :
340 : /*-----------------------------------------------------------------*
341 : * BASOP_cfft_ivas()
342 : *
343 : * Complex valued FFT
344 : *-----------------------------------------------------------------*/
345 :
346 244091 : 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 244091 : BASOP_fftN2( re, im, RotVector_256, 8, 8, s, 8, x, 64 );
357 244091 : s = add( *scale, SCALEFACTOR64 );
358 :
359 244091 : *scale = s;
360 244091 : move16();
361 :
362 244091 : return;
363 : }
364 :
365 :
366 : #undef WMC_TOOL_SKIP
|