]> git.sesse.net Git - x264/blob - tools/checkasm.c
cosmetics: reorganize intra prediction dsp
[x264] / tools / checkasm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "common/common.h"
6 #include "common/cpu.h"
7 #ifdef HAVE_MMXEXT
8 #include "common/i386/pixel.h"
9 #include "common/i386/dct.h"
10 #include "common/i386/mc.h"
11 #endif
12 #ifdef ARCH_PPC
13 #include "common/ppc/pixel.h"
14 #include "common/ppc/mc.h"
15 #endif
16
17 /* buf1, buf2: initialised to randome data and shouldn't write into them */
18 uint8_t * buf1, * buf2;
19 /* buf3, buf4: used to store output */
20 uint8_t * buf3, * buf4;
21 /* buf5: temp */
22 uint8_t * buf5;
23
24 #define report( name ) { \
25     if( used_asm ) \
26         fprintf( stderr, " - %-21s [%s]\n", name, ok ? "OK" : "FAILED" ); \
27     if( !ok ) ret = -1; \
28 }
29
30 static int check_pixel( int cpu_ref, int cpu_new )
31 {
32     x264_pixel_function_t pixel_c;
33     x264_pixel_function_t pixel_ref;
34     x264_pixel_function_t pixel_asm;
35     int ret = 0, ok, used_asm;
36     int i;
37
38     x264_pixel_init( 0, &pixel_c );
39     x264_pixel_init( cpu_ref, &pixel_ref );
40     x264_pixel_init( cpu_new, &pixel_asm );
41
42 #define TEST_PIXEL( name ) \
43     for( i = 0, ok = 1, used_asm = 0; i < 7; i++ ) \
44     { \
45         int res_c, res_asm; \
46         if( pixel_asm.name[i] != pixel_ref.name[i] ) \
47         { \
48             used_asm = 1; \
49             res_c   = pixel_c.name[i]( buf1, 32, buf2, 24 ); \
50             res_asm = pixel_asm.name[i]( buf1, 32, buf2, 24 ); \
51             if( res_c != res_asm ) \
52             { \
53                 ok = 0; \
54                 fprintf( stderr, #name "[%d]: %d != %d [FAILED]\n", i, res_c, res_asm ); \
55             } \
56         } \
57     } \
58     report( "pixel " #name " :" );
59
60     TEST_PIXEL( sad );
61     TEST_PIXEL( ssd );
62     TEST_PIXEL( satd );
63
64     return ret;
65 }
66
67 static int check_dct( int cpu_ref, int cpu_new )
68 {
69     x264_dct_function_t dct_c;
70     x264_dct_function_t dct_ref;
71     x264_dct_function_t dct_asm;
72     int ret = 0, ok, used_asm;
73     int16_t dct1[16][4][4] __attribute((aligned(16)));
74     int16_t dct2[16][4][4] __attribute((aligned(16)));
75
76     x264_dct_init( 0, &dct_c );
77     x264_dct_init( cpu_ref, &dct_ref);
78     x264_dct_init( cpu_new, &dct_asm );
79 #define TEST_DCT( name, t1, t2, size ) \
80     if( dct_asm.name != dct_ref.name ) \
81     { \
82         used_asm = 1; \
83         dct_c.name( t1, buf1, 32, buf2, 24 ); \
84         dct_asm.name( t2, buf1, 32, buf2, 24 ); \
85         if( memcmp( t1, t2, size ) ) \
86         { \
87             ok = 0; \
88             fprintf( stderr, #name " [FAILED]\n" ); \
89         } \
90     }
91     ok = 1; used_asm = 0;
92     TEST_DCT( sub4x4_dct, dct1[0], dct2[0], 16*2 );
93     TEST_DCT( sub8x8_dct, dct1, dct2, 16*2*4 );
94     TEST_DCT( sub16x16_dct, dct1, dct2, 16*2*16 );
95     report( "sub_dct4 :" );
96
97     ok = 1; used_asm = 0;
98     TEST_DCT( sub8x8_dct8, (void*)dct1[0], (void*)dct2[0], 64*2 );
99     TEST_DCT( sub16x16_dct8, (void*)dct1, (void*)dct2, 64*2*4 );
100     report( "sub_dct8 :" );
101 #undef TEST_DCT
102
103     /* copy coefs because idct8 modifies them in place */
104     memcpy( buf5, dct1, 512 );
105
106 #define TEST_IDCT( name ) \
107     if( dct_asm.name != dct_ref.name ) \
108     { \
109         used_asm = 1; \
110         memcpy( buf3, buf1, 32*32 ); \
111         memcpy( buf4, buf1, 32*32 ); \
112         memcpy( dct1, buf5, 512 ); \
113         memcpy( dct2, buf5, 512 ); \
114         dct_c.name( buf3, 32, (void*)dct1 ); \
115         dct_asm.name( buf4, 32, (void*)dct2 ); \
116         if( memcmp( buf3, buf4, 32*32 ) ) \
117         { \
118             ok = 0; \
119             fprintf( stderr, #name " [FAILED]\n" ); \
120         } \
121     }
122     ok = 1; used_asm = 0;
123     TEST_IDCT( add4x4_idct );
124     TEST_IDCT( add8x8_idct );
125     TEST_IDCT( add16x16_idct );
126     report( "add_idct4 :" );
127
128     ok = 1; used_asm = 0;
129     TEST_IDCT( add8x8_idct8 );
130     TEST_IDCT( add16x16_idct8 );
131     report( "add_idct8 :" );
132 #undef TEST_IDCT
133
134     ok = 1; used_asm = 0;
135     if( dct_asm.dct4x4dc != dct_ref.dct4x4dc )
136     {
137         int16_t dct1[4][4] __attribute((aligned(16))) = { {-12, 42, 23, 67},{2, 90, 89,56}, {67,43,-76,91},{56,-78,-54,1}};
138         int16_t dct2[4][4] __attribute((aligned(16))) = { {-12, 42, 23, 67},{2, 90, 89,56}, {67,43,-76,91},{56,-78,-54,1}};
139         used_asm = 1;
140         dct_c.dct4x4dc( dct1 );
141         dct_asm.dct4x4dc( dct2 );
142         if( memcmp( dct1, dct2, 32 ) )
143         {
144             ok = 0;
145             fprintf( stderr, " - dct4x4dc :        [FAILED]\n" );
146         }
147     }
148     if( dct_asm.dct4x4dc != dct_ref.dct4x4dc )
149     {
150         int16_t dct1[4][4] __attribute((aligned(16))) = { {-12, 42, 23, 67},{2, 90, 89,56}, {67,43,-76,91},{56,-78,-54,1}};
151         int16_t dct2[4][4] __attribute((aligned(16))) = { {-12, 42, 23, 67},{2, 90, 89,56}, {67,43,-76,91},{56,-78,-54,1}};
152         used_asm = 1;
153         dct_c.idct4x4dc( dct1 );
154         dct_asm.idct4x4dc( dct2 );
155         if( memcmp( dct1, dct2, 32 ) )
156         {
157             ok = 0;
158             fprintf( stderr, " - idct4x4dc :        [FAILED]\n" );
159         }
160     }
161     report( "(i)dct4x4dc :" );
162
163     ok = 1; used_asm = 0;
164     if( dct_asm.dct2x2dc != dct_ref.dct2x2dc )
165     {
166         int16_t dct1[2][2] __attribute((aligned(16))) = { {-12, 42},{2, 90}};
167         int16_t dct2[2][2] __attribute((aligned(16))) = { {-12, 42},{2, 90}};
168         used_asm = 1;
169         dct_c.dct2x2dc( dct1 );
170         dct_asm.dct2x2dc( dct2 );
171         if( memcmp( dct1, dct2, 4*2 ) )
172         {
173             ok = 0;
174             fprintf( stderr, " - dct2x2dc :        [FAILED]\n" );
175         }
176     }
177     if( dct_asm.idct2x2dc != dct_ref.idct2x2dc )
178     {
179         int16_t dct1[2][2] __attribute((aligned(16))) = { {-12, 42},{2, 90}};
180         int16_t dct2[2][2] __attribute((aligned(16))) = { {-12, 42},{2, 90}};
181         used_asm = 1;
182         dct_c.idct2x2dc( dct1 );
183         dct_asm.idct2x2dc( dct2 );
184         if( memcmp( dct1, dct2, 4*2 ) )
185         {
186             ok = 0;
187             fprintf( stderr, " - idct2x2dc :       [FAILED]\n" );
188         }
189     }
190     report( "(i)dct2x2dc :" );
191
192     return ret;
193 }
194
195 static int check_mc( int cpu_ref, int cpu_new )
196 {
197     x264_mc_functions_t mc_c;
198     x264_mc_functions_t mc_ref;
199     x264_mc_functions_t mc_a;
200
201     uint8_t *src     = &buf1[2*32+2];
202     uint8_t *src2[4] = { &buf1[2*32+2],  &buf1[7*32+2],
203                          &buf1[12*32+2], &buf1[17*32+2] };
204     uint8_t *dst1    = &buf3[2*32+2];
205     uint8_t *dst2    = &buf4[2*32+2];
206
207     int dx, dy, i, w;
208     int ret = 0, ok, used_asm;
209
210     x264_mc_init( 0, &mc_c );
211     x264_mc_init( cpu_ref, &mc_ref );
212     x264_mc_init( cpu_new, &mc_a );
213
214 #define MC_TEST_LUMA( w, h ) \
215         if( mc_a.mc_luma != mc_ref.mc_luma ) \
216         { \
217             used_asm = 1; \
218             memset(buf3, 0xCD, 1024); \
219             memset(buf4, 0xCD, 1024); \
220             mc_c.mc_luma( src2, 32, dst1, 16, dx, dy, w, h );     \
221             mc_a.mc_luma( src2, 32, dst2, 16, dx, dy, w, h );   \
222             if( memcmp( buf3, buf4, 1024 ) )               \
223             { \
224                 fprintf( stderr, "mc_luma[mv(%d,%d) %2dx%-2d]     [FAILED]\n", dx, dy, w, h );   \
225                 ok = 0; \
226             } \
227         }
228
229 #define MC_TEST_CHROMA( w, h ) \
230         if( mc_a.mc_chroma != mc_ref.mc_chroma ) \
231         { \
232             used_asm = 1; \
233             memset(buf3, 0xCD, 1024); \
234             memset(buf4, 0xCD, 1024); \
235             mc_c.mc_chroma( src, 32, dst1, 16, dx, dy, w, h );     \
236             mc_a.mc_chroma( src, 32, dst2, 16, dx, dy, w, h );   \
237             if( memcmp( buf3, buf4, 1024 ) )               \
238             { \
239                 fprintf( stderr, "mc_chroma[mv(%d,%d) %2dx%-2d]     [FAILED]\n", dx, dy, w, h );   \
240                 ok = 0; \
241             } \
242         }
243     ok = 1; used_asm = 0;
244     for( dy = 0; dy < 4; dy++ )
245         for( dx = 0; dx < 4; dx++ )
246         {
247             MC_TEST_LUMA( 16, 16 );
248             MC_TEST_LUMA( 16, 8 );
249             MC_TEST_LUMA( 8, 16 );
250             MC_TEST_LUMA( 8, 8 );
251             MC_TEST_LUMA( 8, 4 );
252             MC_TEST_LUMA( 4, 8 );
253             MC_TEST_LUMA( 4, 4 );
254         }
255     report( "mc luma :" );
256
257     ok = 1; used_asm = 0;
258     for( dy = 0; dy < 9; dy++ )
259         for( dx = 0; dx < 9; dx++ )
260         {
261             MC_TEST_CHROMA( 8, 8 );
262             MC_TEST_CHROMA( 8, 4 );
263             MC_TEST_CHROMA( 4, 8 );
264             MC_TEST_CHROMA( 4, 4 );
265             MC_TEST_CHROMA( 4, 2 );
266             MC_TEST_CHROMA( 2, 4 );
267             MC_TEST_CHROMA( 2, 2 );
268         }
269     report( "mc chroma :" );
270 #undef MC_TEST_LUMA
271 #undef MC_TEST_CHROMA
272
273 #define MC_TEST_AVG( name, ... ) \
274     for( i = 0, ok = 1, used_asm = 0; i < 10; i++ ) \
275     { \
276         memcpy( buf3, buf1, 1024 ); \
277         memcpy( buf4, buf1, 1024 ); \
278         if( mc_a.name[i] != mc_ref.name[i] ) \
279         { \
280             used_asm = 1; \
281             mc_c.name[i]( buf3, 32, buf2, 24, ##__VA_ARGS__ ); \
282             mc_a.name[i]( buf4, 32, buf2, 24, ##__VA_ARGS__ ); \
283             if( memcmp( buf3, buf4, 1024 ) )               \
284             { \
285                 ok = 0; \
286                 fprintf( stderr, #name "[%d]: [FAILED]\n", i ); \
287             } \
288         } \
289     }
290     MC_TEST_AVG( avg );
291     report( "mc avg :" );
292     for( w = -64; w <= 128 && ok; w++ )
293         MC_TEST_AVG( avg_weight, w );
294     report( "mc wpredb :" );
295
296     return ret;
297 }
298
299 static int check_deblock( int cpu_ref, int cpu_new )
300 {
301     x264_deblock_function_t db_c;
302     x264_deblock_function_t db_ref;
303     x264_deblock_function_t db_a;
304     int ret = 0, ok = 1, used_asm = 0;
305     int alphas[36], betas[36];
306     int8_t tcs[36][4];
307     int a, c, i, j;
308
309     x264_deblock_init( 0, &db_c );
310     x264_deblock_init( cpu_ref, &db_ref );
311     x264_deblock_init( cpu_new, &db_a );
312
313     /* not exactly the real values of a,b,tc but close enough */
314     a = 255; c = 250;
315     for( i = 35; i >= 0; i-- )
316     {
317         alphas[i] = a;
318         betas[i] = (i+1)/2;
319         tcs[i][0] = tcs[i][2] = (c+6)/10;
320         tcs[i][1] = tcs[i][3] = (c+9)/20;
321         a = a*9/10;
322         c = c*9/10;
323     }
324
325 #define TEST_DEBLOCK( name, ... ) \
326     for( i = 0; i < 36; i++ ) \
327     { \
328         for( j = 0; j < 1024; j++ ) \
329             /* two distributions of random to excersize different failure modes */\
330             buf1[j] = rand() & (i&1 ? 0xf : 0xff ); \
331         memcpy( buf3, buf1, 1024 ); \
332         memcpy( buf4, buf1, 1024 ); \
333         if( db_a.name != db_ref.name ) \
334         { \
335             used_asm = 1; \
336             db_c.name( &buf3[8*32], 32, alphas[i], betas[i], ##__VA_ARGS__ ); \
337             db_a.name( &buf4[8*32], 32, alphas[i], betas[i], ##__VA_ARGS__ ); \
338             if( memcmp( buf3, buf4, 1024 ) )               \
339             { \
340                 ok = 0; \
341                 fprintf( stderr, #name "(a=%d, b=%d): [FAILED]\n", alphas[i], betas[i] ); \
342                 break; \
343             } \
344         } \
345     }
346
347     TEST_DEBLOCK( deblock_h_luma, tcs[i] );
348     TEST_DEBLOCK( deblock_v_luma, tcs[i] );
349     TEST_DEBLOCK( deblock_h_chroma, tcs[i] );
350     TEST_DEBLOCK( deblock_v_chroma, tcs[i] );
351     TEST_DEBLOCK( deblock_h_luma_intra );
352     TEST_DEBLOCK( deblock_v_luma_intra );
353     TEST_DEBLOCK( deblock_h_chroma_intra );
354     TEST_DEBLOCK( deblock_v_chroma_intra );
355
356     report( "deblock :" );
357
358     return ret;
359 }
360
361 static int check_quant( int cpu_ref, int cpu_new )
362 {
363     x264_quant_function_t qf_c;
364     x264_quant_function_t qf_ref;
365     x264_quant_function_t qf_a;
366     int16_t dct1[64], dct2[64];
367     uint8_t cqm_buf[64];
368     int ret = 0, ok, used_asm;
369     int oks[2] = {1,1}, used_asms[2] = {0,0};
370     int i, i_cqm;
371     x264_t h_buf;
372     x264_t *h = &h_buf;
373     h->pps = h->pps_array;
374     x264_param_default( &h->param );
375
376     for( i_cqm = 0; i_cqm < 4; i_cqm++ )
377     {
378         if( i_cqm == 0 )
379             for( i = 0; i < 6; i++ )
380                 h->pps->scaling_list[i] = x264_cqm_flat16;
381         else if( i_cqm == 1 )
382             for( i = 0; i < 6; i++ )
383                 h->pps->scaling_list[i] = x264_cqm_jvt[i];
384         else
385         {
386             if( i_cqm == 2 )
387                 for( i = 0; i < 64; i++ )
388                     cqm_buf[i] = 10 + rand() % 246;
389             else
390                 for( i = 0; i < 64; i++ )
391                     cqm_buf[i] = 1;
392             for( i = 0; i < 6; i++ )
393                 h->pps->scaling_list[i] = cqm_buf;
394         }
395
396         x264_cqm_init( h );
397         x264_quant_init( h, 0, &qf_c );
398         x264_quant_init( h, cpu_ref, &qf_ref );
399         x264_quant_init( h, cpu_new, &qf_a );
400
401 #define TEST_QUANT( name, cqm ) \
402         if( qf_a.name != qf_ref.name ) \
403         { \
404             used_asms[0] = 1; \
405             for( i = 0; i < 64; i++ ) \
406                 dct1[i] = dct2[i] = (rand() & 0x1fff) - 0xfff; \
407             qf_c.name( (void*)dct1, cqm, 20, (1<<20)/6 ); \
408             qf_a.name( (void*)dct2, cqm, 20, (1<<20)/6 ); \
409             if( memcmp( dct1, dct2, 64*2 ) )       \
410             { \
411                 oks[0] = 0; \
412                 fprintf( stderr, #name "(cqm=%d): [FAILED]\n", i_cqm ); \
413             } \
414         }
415
416         TEST_QUANT( quant_8x8_core, *h->quant8_mf[CQM_8IY] );
417         TEST_QUANT( quant_8x8_core, *h->quant8_mf[CQM_8PY] );
418         TEST_QUANT( quant_4x4_core, *h->quant4_mf[CQM_4IY] );
419         TEST_QUANT( quant_4x4_core, *h->quant4_mf[CQM_4PY] );
420         TEST_QUANT( quant_4x4_dc_core, ***h->quant4_mf[CQM_4IY] );
421         TEST_QUANT( quant_2x2_dc_core, ***h->quant4_mf[CQM_4IC] );
422
423 #define TEST_DEQUANT( name, quant, dqm, cqm, shift ) \
424         if( qf_a.name != qf_ref.name ) \
425         { \
426             int qp; \
427             used_asms[1] = 1; \
428             for( qp = 51; qp > 0; qp-- ) \
429             { \
430                 for( i = 0; i < 64; i++ ) \
431                     dct1[i] = dct2[i] = (rand() & 0x1fff) - 0xfff; \
432                 qf_c.quant( (void*)dct1, cqm[qp%6], shift+qp/6, 0 ); \
433                 memcpy( dct2, dct1, sizeof(dct2) ); \
434                 qf_c.name( (void*)dct1, dqm, qp ); \
435                 qf_a.name( (void*)dct2, dqm, qp ); \
436                 if( memcmp( dct1, dct2, 64*2 ) ) \
437                 { \
438                     oks[1] = 0; \
439                     fprintf( stderr, #name "(qp=%d, cqm=%d): [FAILED]\n", qp, i_cqm ); \
440                     break; \
441                 } \
442             } \
443         }
444
445         TEST_DEQUANT( dequant_8x8, quant_8x8_core, h->dequant8_mf[CQM_8PY], h->quant8_mf[CQM_8PY], 16 );
446         TEST_DEQUANT( dequant_4x4, quant_4x4_core, h->dequant4_mf[CQM_4PY], h->quant4_mf[CQM_4PY], 15 );
447     }
448
449     ok = oks[0]; used_asm = used_asms[0];
450     report( "quant :" );
451
452     ok = oks[1]; used_asm = used_asms[1];
453     report( "dequant :" );
454
455     return ret;
456 }
457
458 static int check_intra( int cpu_ref, int cpu_new )
459 {
460     int ret = 0, ok = 1, used_asm = 0;
461     int i;
462     struct
463     {
464         x264_predict_t      predict_16x16[4+3];
465         x264_predict_t      predict_8x8c[4+3];
466         x264_predict8x8_t   predict_8x8[9+3];
467         x264_predict_t      predict_4x4[9+3];
468     } ip_c, ip_ref, ip_a;
469
470     x264_predict_16x16_init( 0, ip_c.predict_16x16 );
471     x264_predict_8x8c_init( 0, ip_c.predict_8x8c );
472     x264_predict_8x8_init( 0, ip_c.predict_8x8 );
473     x264_predict_4x4_init( 0, ip_c.predict_4x4 );
474
475     x264_predict_16x16_init( cpu_ref, ip_ref.predict_16x16 );
476     x264_predict_8x8c_init( cpu_ref, ip_ref.predict_8x8c );
477     x264_predict_8x8_init( cpu_ref, ip_ref.predict_8x8 );
478     x264_predict_4x4_init( cpu_ref, ip_ref.predict_4x4 );
479
480     x264_predict_16x16_init( cpu_new, ip_a.predict_16x16 );
481     x264_predict_8x8c_init( cpu_new, ip_a.predict_8x8c );
482     x264_predict_8x8_init( cpu_new, ip_a.predict_8x8 );
483     x264_predict_4x4_init( cpu_new, ip_a.predict_4x4 );
484
485 #define INTRA_TEST( name, dir, ... ) \
486     if( ip_a.name[dir] != ip_ref.name[dir] )\
487     { \
488         used_asm = 1; \
489         memcpy( buf3, buf1, 32*20 );\
490         memcpy( buf4, buf1, 32*20 );\
491         ip_c.name[dir]( buf3+48, 32, ##__VA_ARGS__ );\
492         ip_a.name[dir]( buf4+48, 32, ##__VA_ARGS__ );\
493         if( memcmp( buf3, buf4, 32*20 ) )\
494         {\
495             fprintf( stderr, #name "[%d] :  [FAILED]\n", dir );\
496             ok = 0;\
497         }\
498     }
499
500     for( i = 0; i < 12; i++ )
501         INTRA_TEST( predict_4x4, i );
502     for( i = 0; i < 12; i++ )
503         INTRA_TEST( predict_8x8, i, 0xf );
504     for( i = 0; i < 7; i++ )
505         INTRA_TEST( predict_8x8c, i );
506     for( i = 0; i < 7; i++ )
507         INTRA_TEST( predict_16x16, i );
508
509     report( "intra pred :" );
510     return ret;
511 }
512
513 int check_all( int cpu_ref, int cpu_new )
514 {
515     return check_pixel( cpu_ref, cpu_new )
516          + check_dct( cpu_ref, cpu_new )
517          + check_mc( cpu_ref, cpu_new )
518          + check_intra( cpu_ref, cpu_new )
519          + check_deblock( cpu_ref, cpu_new )
520          + check_quant( cpu_ref, cpu_new );
521 }
522
523 int main()
524 {
525     int ret = 0;
526     int i;
527
528     buf1 = x264_malloc( 1024 ); /* 32 x 32 */
529     buf2 = x264_malloc( 1024 );
530     buf3 = x264_malloc( 1024 );
531     buf4 = x264_malloc( 1024 );
532     buf5 = x264_malloc( 1024 );
533
534     srand( x264_mdate() );
535
536     for( i = 0; i < 1024; i++ )
537     {
538         buf1[i] = rand() & 0xFF;
539         buf2[i] = rand() & 0xFF;
540         buf3[i] = buf4[i] = 0;
541     }
542
543 #ifdef HAVE_MMXEXT
544     fprintf( stderr, "x264: MMXEXT against C\n" );
545     ret = check_all( 0, X264_CPU_MMX | X264_CPU_MMXEXT );
546 #ifdef HAVE_SSE2
547     if( x264_cpu_detect() & X264_CPU_SSE2 )
548     {
549         fprintf( stderr, "\nx264: SSE2 against C\n" );
550         ret |= check_all( X264_CPU_MMX | X264_CPU_MMXEXT,
551                           X264_CPU_MMX | X264_CPU_MMXEXT | X264_CPU_SSE | X264_CPU_SSE2 );
552     }
553 #endif
554 #elif ARCH_PPC
555     fprintf( stderr, "x264: ALTIVEC against C\n" );
556     ret = check_all( 0, X264_CPU_ALTIVEC );
557 #endif
558
559     if( ret == 0 )
560     {
561         fprintf( stderr, "x264: All tests passed Yeah :)\n" );
562         return 0;
563     }
564     fprintf( stderr, "x264: at least one test has failed. Go and fix that Right Now!\n" );
565     return -1;
566 }
567