1 /* File generate.c. */
2
3 /* Copyright (C) 1992 by Jeffrey S. Leon. This software may be used freely
4 for educational and research purposes. Any other use requires permission
5 from the author. */
6
7 /* Main program for generate command, which may be used
8 to find a base and strong generating set for a permutation group using
9 the random Schreier and/or Schreier-Todd-Coxeter-Sims methods. The format
10 of the command is:
11
12 generate <options> <permGroup> <generatedPermGroup>
13
14 where the meaning of the parameters is as follows:
15
16 <permGroup>: the permutation group G for which a base and strong
17 generating set is to be found.
18
19 <generatedPermGroup>: the same permutation group G with a base and strong
20 generating set, depending on options, possibly a
21 strong presentation.
22
23 The general options are as follows:
24
25 -nr Omit random-Schreier phase.
26
27 -ns Omit Schreier-Todd-Coxeter-Sims phase (automatically
28 omitted if order is known in advance and random-Schreier
29 phases generates full order, unless the -p option is given.
30
31 -p Find a presentation.
32
33 -q Don't write status information to standard output.
34
35 -in:<group> Group G is contained in <group>. Only base of <group> is
36 used; <group> need not be valid as long as its base ,
37 base size, and degree fields are filled in correctly.
38
39 -overwrite Overwrite, rather than append to, the output file.
40
41 -i Image format for output group.
42
43 -c Cycle format for output group.
44
45 -gn:<name>
46
47 Options applicable specifically to the random-Schreier phase are:
48
49 -s:<integer> Seed for random number generator.
50
51 -tr:<integer> Random Schreier phase terminates after this many
52 consecutive "successes" (quasi-random elements that
53 are factorable).
54
55 -ti:<integer> This many consecutive non-involutory generators will
56 be rejected in an attempt to choose involutory generators.
57
58 -th:k This many consecutive generators will be rejected in
59 an attempt to choose a generator of order 3 (or less).
60
61 -nro Suppress normal attempt to reduce generator order by
62 replacing generators with powers.
63
64 -wi:w,x Here w and x are integers with w <= x. The word length
65 increment will be random between w and x.
66
67 -z Redundant strong generators will be removed after the
68 algorithm completes..
69
70 Options applicable to the STCS phase are:
71
72 -go:m Automatically include the order of each generator as a
73 relator when the generator order does not exceed m
74 (default 15).
75
76 -po:m Automatically include the order of each product of
77 generators as a relator when the product order does
78 not exceed m (default 5).
79
80 -x2:m If the STCS phase terminates with more than
81 m generators (excluding inverses), redundant generators
82 are removed.
83
84 -pr:a,b,c,d,e Determines priority for relator selection. The priority
85 of a relator r is a - b * (len+symLen)/2. Relators are
86 selected if their priority exceeds
87 c + d * chosen - e * omitted, where chosen represents the
88 number of relators chosen at this level and omitted
89 represents the number not chosen.
90
91 -sh:i1,k1,i2.. Specifies which cyclic shifts of relators will be
92 used in the Felsch enumeration. Specifies that an
93 i1 position shift will be used if the relator
94 priority exceeds the selection priority by at least
95 k1, etc. By default, all shifts are always used.
96 -x:k Specifies use of up to k extra cosets during enumeration
97 (default 0). When k > 0, a different procedure is
98 used to check point stabilizers.
99
100 -y:m The number of extra cosets used will be
101 m/100 * degree (rounded up), but in no case more than
102 k, as above (default 10). */
103
104
105 #include <stddef.h>
106 #include <errno.h>
107 #include <stdlib.h>
108 #include <stdio.h>
109 #include <string.h>
110 #include <time.h>
111
112 #define MAIN
113
114 #include "group.h"
115 #include "groupio.h"
116 #include "enum.h"
117 #include "storage.h"
118
119 #ifdef ALT_TIME_HEADER
120 #include "cputime.h"
121 #endif
122
123 #ifdef TICK
124 #undef CLK_TCK
125 #define CLK_TCK TICK
126 #endif
127
128 #include "errmesg.h"
129 #include "new.h"
130 #include "readgrp.h"
131 #include "randschr.h"
132 #include "stcs.h"
133 #include "util.h"
134
135 static void nameGenerators(
136 PermGroup *const H,
137 char genNamePrefix[]);
138
139 static void informGenerateTime(
140 clock_t startTime,
141 clock_t randSchrTime,
142 clock_t optGroupTime,
143 clock_t stcsTime);
144
145 static void verifyOptions(void);
146
147 GroupOptions options;
148 STCSOptions sOptions;
149
150 Unsigned relatorSelection[5] = {1000,0,800,0,0};
151 Unsigned shiftSelection[11] = {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
152 UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
153 UNKNOWN};
154 Unsigned shiftPriority[11];
155
156
main(int argc,char * argv[])157 int main( int argc, char *argv[])
158 {
159 char groupFileName[MAX_FILE_NAME_LENGTH] = "",
160 genGroupFileName[MAX_FILE_NAME_LENGTH] = "",
161 containingGroupFileName[MAX_FILE_NAME_LENGTH] = "";
162 char groupLibraryName[MAX_NAME_LENGTH+1] = "",
163 genGroupLibraryName[MAX_NAME_LENGTH+1] = "",
164 genGroupObjectName[MAX_NAME_LENGTH+1] = "",
165 containingGroupLibraryName[MAX_NAME_LENGTH+1] = "",
166 prefix[MAX_FILE_NAME_LENGTH],
167 suffix[MAX_NAME_LENGTH];
168 Unsigned i, j, optionCountPlus1, level;
169 BOOLEAN omitRandomSchreierOption, omitStcsOption, presentationOption,
170 quietOption, cycleFormatFlag, imageFormatFlag, removeRedunStrGens,
171 noBackupFlag;
172 Unsigned trimStrGenSet1, trimStrGenSet2;
173 PermGroup *G, *containingGroup;
174 char comment[60] = "";
175 UnsignedS *pointList = allocIntArrayBaseSize();
176 char tempStr[12];
177 char *strPtr, *commaPtr;
178 Unsigned *knownBase = allocIntArrayBaseSize();
179 RandomSchreierOptions rOptions = {47,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
180 UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN};
181 clock_t startTime, randSchrTime, optGroupTime, stcsTime;
182
183
184 /* Provide usage info if no arguments are specified. */
185 if ( argc == 1 ) {
186 printf( "\nUsage: generate [options] originalPermGroup permGroupWithBaseSGS\n");
187 freeIntArrayBaseSize( pointList);
188 freeIntArrayBaseSize( knownBase);
189 return 0;
190 }
191
192 /* Check for limits option. If present in position 1 give limits and
193 return. */
194 if ( strcmp( argv[1], "-l") == 0 || strcmp( argv[1], "-L") == 0 ) {
195 showLimits();
196 freeIntArrayBaseSize( pointList);
197 freeIntArrayBaseSize( knownBase);
198 return 0;
199 }
200
201 /* Check for verify option. If present, perform verify (Note verifyOptions
202 terminates program). */
203 if ( strcmp( argv[1], "-v") == 0 || strcmp( argv[1], "-V") == 0 )
204 verifyOptions();
205
206 /* Check for 1 or 2 parameters following options. */
207 for ( optionCountPlus1 = 1 ; optionCountPlus1 <= argc-1 &&
208 argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
209 ;
210
211 if ( argc - optionCountPlus1 < 1 || argc - optionCountPlus1 > 2 ) {
212 printf( "\n\nError: 1 or 2 non-option parameters are required.\n");
213 exit(ERROR_RETURN_CODE);
214 }
215
216 /* Process options. */
217 prefix[0] = '\0';
218 suffix[0] = '\0';
219 options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
220 sOptions.maxDeducQueueSize = UNKNOWN;
221 sOptions.genOrderLimit = 13;
222 sOptions.prodOrderLimit = 3;
223 sOptions.maxExtraCosets = 0;
224 sOptions.percentExtraCosets = 10;
225 omitRandomSchreierOption = FALSE;
226 omitStcsOption = TRUE;
227 presentationOption = FALSE;
228 rOptions.reduceGenOrder = TRUE;
229 rOptions.rejectNonInvols = 0;
230 removeRedunStrGens = FALSE;
231 quietOption = FALSE;
232 options.genNamePrefix[0] = '\0';
233 trimStrGenSet1 = 20;
234 trimStrGenSet2 = 20;
235 cycleFormatFlag = FALSE;
236 imageFormatFlag = FALSE;
237 noBackupFlag = FALSE;
238 strcpy( options.outputFileMode, "w");
239 strcpy( options.genNamePrefix, "");
240
241 for ( i = 1 ; i < optionCountPlus1 ; ++i )
242
243 /* General options. */
244 if ( strcmp( argv[i], "-a") == 0 )
245 strcpy( options.outputFileMode, "a");
246 else if ( strcmp( argv[i], "-c") == 0 )
247 cycleFormatFlag = TRUE;
248 else if ( strcmp( argv[i], "-i") == 0 )
249 imageFormatFlag = TRUE;
250 else if ( strncmp( argv[i], "-mb:", 4) == 0 ) {
251 errno = 0;
252 options.maxBaseSize = (Unsigned) strtol(argv[i]+4,NULL,0);
253 if ( errno )
254 ERROR( "main (cent)", "Invalid syntax for -mb option")
255 }
256 else if ( strncmp( argv[i], "-mw:", 4) == 0 ) {
257 errno = 0;
258 options.maxWordLength = (Unsigned) strtol(argv[i]+4,NULL,0);
259 if ( errno )
260 ERROR( "main (cent)", "Invalid syntax for -mw option")
261 }
262 else if ( strncmp(argv[i],"-n:",3) == 0 )
263 strcpy( genGroupObjectName, argv[i]+3);
264 else if ( strcmp( argv[i], "-nb") == 0 )
265 noBackupFlag = TRUE;
266 else if ( strcmp( argv[i], "-overwrite") == 0 )
267 strcpy( options.outputFileMode, "w");
268 else if ( strncmp( argv[i], "-p:", 3) == 0 ) {
269 strcpy( prefix, argv[i]+3);
270 }
271 else if ( strcmp( argv[i], "-q") == 0 )
272 quietOption = TRUE;
273 else if ( strncmp( argv[i], "-t:", 3) == 0 ) {
274 strcpy( suffix, argv[i]+3);
275 }
276 else if ( strcmp( argv[i], "-z") == 0 ) {
277 removeRedunStrGens = TRUE;
278 }
279
280 /* Method selection options. */
281 else if ( strcmp( argv[i], "-nr") == 0 )
282 omitRandomSchreierOption = TRUE;
283 else if ( strcmp( argv[i], "-stcs") == 0 )
284 omitStcsOption = FALSE;
285
286 /* Random Schreier options. */
287 else if ( strcmp( argv[i], "-nro") == 0 )
288 rOptions.reduceGenOrder = FALSE;
289 else if ( strncmp(argv[i],"-s:",3) == 0 ) {
290 errno = 0;
291 rOptions.initialSeed = (unsigned long) strtol( argv[i]+3, NULL, 0);
292 if ( errno )
293 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
294 }
295 else if ( strncmp(argv[i],"-ti:",4) == 0 ) {
296 errno = 0;
297 rOptions.rejectNonInvols = (unsigned long) strtol( argv[i]+4, NULL, 0);
298 if ( errno )
299 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
300 }
301 else if ( strncmp(argv[i],"-tr:",4) == 0 ) {
302 errno = 0;
303 rOptions.stopAfter = (unsigned long) strtol( argv[i]+4, NULL, 0);
304 if ( errno )
305 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
306 }
307 else if ( strncmp( argv[i], "-wi:", 4) == 0 ) {
308 errno = 0;
309 rOptions.minWordLengthIncrement = (unsigned long) strtol( argv[i]+4, &commaPtr, 0);
310 if ( errno || *commaPtr != ',' )
311 ERROR1s( "main (generate command)", "Invalid syntax in option ",
312 argv[i], ".")
313 rOptions.maxWordLengthIncrement = (unsigned long) strtol( commaPtr+1, NULL, 0);
314 if ( errno )
315 ERROR1s( "main (generate command)", "Invalid syntax in option ",
316 argv[i], ".")
317 }
318
319 /* STCS options. */
320 else if ( strncmp( argv[i], "-in:", 4) == 0 ) {
321 parseLibraryName( argv[i]+4, "", "", containingGroupFileName,
322 containingGroupLibraryName);
323 }
324 else if ( strncmp(argv[i],"-pr:",4) == 0 ) {
325 errno = 0;
326 commaPtr = argv[i]+3;
327 for ( j = 0 ; j <= 4 ; ++j ) {
328 strPtr = commaPtr + 1;
329 relatorSelection[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
330 if ( errno || ( j < 4 && *commaPtr != ',') )
331 ERROR1s( "main (generate command)", "Invalid option ", argv[i],
332 ".")
333 }
334 }
335 else if ( strncmp(argv[i],"-sh:",4) == 0 ) {
336 errno = 0;
337 commaPtr = argv[i]+3;
338 for ( j = 0 ; j < 10 && *commaPtr != '\0' ; ++j ) {
339 strPtr = commaPtr + 1;
340 shiftSelection[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
341 if ( errno || *commaPtr != ',' )
342 ERROR1s( "main (generate command)", "Invalid option ", argv[i],
343 ".")
344 strPtr = commaPtr + 1;
345 shiftPriority[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
346 if ( errno || (*commaPtr != ',' && *commaPtr != '\0') )
347 ERROR1s( "main (generate command)", "Invalid option ", argv[i],
348 ".")
349 }
350 }
351 else if ( strncmp(argv[i],"-th:",4) == 0 ) {
352 errno = 0;
353 rOptions.rejectHighOrder = (unsigned long) strtol( argv[i]+4, NULL, 0);
354 if ( errno )
355 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
356 }
357 else if ( strncmp(argv[i],"-go:",4) == 0 ) {
358 errno = 0;
359 sOptions.genOrderLimit = (unsigned long) strtol( argv[i]+4, NULL, 0);
360 if ( errno )
361 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
362 }
363 else if ( strncmp(argv[i],"-po:",4) == 0 ) {
364 errno = 0;
365 sOptions.prodOrderLimit = (unsigned long) strtol( argv[i]+4, NULL, 0);
366 if ( errno )
367 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
368 }
369 else if ( strncmp(argv[i],"-x:",3) == 0 ) {
370 errno = 0;
371 sOptions.maxExtraCosets = (unsigned long) strtol( argv[i]+3, NULL, 0);
372 if ( errno )
373 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
374 }
375 else if ( strncmp(argv[i],"-y:",3) == 0 ) {
376 errno = 0;
377 sOptions.percentExtraCosets = (unsigned long) strtol( argv[i]+3, NULL, 0);
378 if ( errno )
379 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
380 }
381 else
382 ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
383
384 /* Compute maximum degree and word length. */
385 options.maxWordLength = 200 + 5 * options.maxBaseSize;
386 options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
387
388
389 /* Compute names for input and output groups. */
390 parseLibraryName( argv[optionCountPlus1], prefix, suffix, groupFileName,
391 groupLibraryName);
392 if ( argc - optionCountPlus1 == 2 )
393 parseLibraryName( argv[optionCountPlus1+1], "", "", genGroupFileName,
394 genGroupLibraryName);
395 else {
396 strcpy( genGroupFileName, groupFileName);
397 strcpy( genGroupLibraryName, groupLibraryName);
398 }
399
400 /* Set initialize option for STCS. */
401 sOptions.initialize = omitRandomSchreierOption;
402
403 /* Set default generator name prefix, if not specified. */
404 if ( options.genNamePrefix[0] == ' ' )
405 strncpy( options.genNamePrefix, genGroupLibraryName, 4);
406
407 /* Read in input group, and base for containing group, if requested. */
408 G = readPermGroup( groupFileName, groupLibraryName, 0, "");
409 if ( containingGroupFileName[0] ) {
410 containingGroup = readPermGroup( containingGroupFileName,
411 containingGroupLibraryName, G->degree, "");
412 for ( i = 1 ; i <= containingGroup->baseSize ; ++i )
413 knownBase[i] = containingGroup->base[i];
414 knownBase[containingGroup->baseSize+1] = 0;
415 deletePermGroup( containingGroup);
416 }
417
418 startTime = CPU_TIME();
419
420 /* Apply random Schreier algorithm. */
421 if ( !omitRandomSchreierOption ) {
422 /* SETUP OPTIONS STRING */
423 randomSchreier( G, rOptions);
424 if ( removeRedunStrGens )
425 removeRedunSGens( G, 1);
426 }
427 randSchrTime = CPU_TIME();
428
429 optGroupTime = CPU_TIME();
430
431 /* Apply Schreier-Todd-Coxeter-Sims algorithm, if appropriate. */
432 if ( !omitStcsOption /* FIX THIS */ )
433 schreierToddCoxeterSims( G, knownBase);
434 stcsTime = CPU_TIME();
435
436 if ( !quietOption ) {
437 informGroup(G);
438 printf( "\n Base: ");
439 for ( level = 1 ; level <= G->baseSize ; ++level )
440 printf( " %5u", G->base[level]);
441 printf( "\n Basic orbit lengths:");
442 for ( level = 1 ; level <= G->baseSize ; ++level )
443 printf( " %5u", G->basicOrbLen[level]);
444 printf( "\n");
445 informGenerateTime( startTime, randSchrTime, optGroupTime, stcsTime);
446 }
447
448 /* Write out the generated group. */
449 sprintf( comment, "The group %s, base and strong generating set constucted.",
450 G->name);
451 if ( cycleFormatFlag )
452 G->printFormat = cycleFormat;
453 if ( imageFormatFlag )
454 G->printFormat = imageFormat;
455 if ( genGroupObjectName[0] )
456 strcpy( G->name, genGroupObjectName);
457 if ( argc - optionCountPlus1 == 1 && !noBackupFlag )
458 if ( rename(groupFileName,"oldgroup") == -1 )
459 ERROR1s( "main (generate command)", "Original group ", groupFileName,
460 " could not be renamed as oldgroup.")
461
462 writePermGroup( genGroupFileName, genGroupLibraryName, G, comment);
463
464 /* Free pseudo-stack storage. */
465 freeIntArrayBaseSize( pointList);
466 freeIntArrayBaseSize( knownBase);
467
468 return 0;
469 }
470
471
472 /*-------------------------- nameGenerators ------------------------------*/
473
nameGenerators(PermGroup * const H,char genNamePrefix[])474 static void nameGenerators(
475 PermGroup *const H,
476 char genNamePrefix[])
477 {
478 Unsigned i;
479 Permutation *gen;
480
481 if ( genNamePrefix[0] == '\0' ) {
482 strncpy( genNamePrefix, H->name, 4);
483 genNamePrefix[4] = '\0';
484 }
485 for ( gen = H->generator , i = 1 ; gen ; gen = gen->next , ++i ) {
486 strcpy( gen->name, genNamePrefix);
487 sprintf( gen->name + strlen(gen->name), "%02d", i);
488 }
489 }
490
491
492 /*-------------------------- verifyOptions -------------------------------*/
493
verifyOptions(void)494 static void verifyOptions(void)
495 {
496 CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
497 MAX_PRIME_FACTORS,
498 MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
499 MAX_EXTRA, XLARGE, SGND, NFLT};
500 extern void xaddsge( CompileOptions *cOpts);
501 extern void xbitman( CompileOptions *cOpts);
502 extern void xchbase( CompileOptions *cOpts);
503 extern void xcopy ( CompileOptions *cOpts);
504 extern void xcstbor( CompileOptions *cOpts);
505 extern void xerrmes( CompileOptions *cOpts);
506 extern void xessent( CompileOptions *cOpts);
507 extern void xfactor( CompileOptions *cOpts);
508 extern void xinform( CompileOptions *cOpts);
509 extern void xnew ( CompileOptions *cOpts);
510 extern void xoldcop( CompileOptions *cOpts);
511 extern void xpermgr( CompileOptions *cOpts);
512 extern void xpermut( CompileOptions *cOpts);
513 extern void xprimes( CompileOptions *cOpts);
514 extern void xrandgr( CompileOptions *cOpts);
515 extern void xrandsc( CompileOptions *cOpts);
516 extern void xreadgr( CompileOptions *cOpts);
517 extern void xrelato( CompileOptions *cOpts);
518 extern void xstcs ( CompileOptions *cOpts);
519 extern void xstorag( CompileOptions *cOpts);
520 extern void xtoken ( CompileOptions *cOpts);
521 extern void xutil ( CompileOptions *cOpts);
522
523 xaddsge( &mainOpts);
524 xbitman( &mainOpts);
525 xchbase( &mainOpts);
526 xcopy ( &mainOpts);
527 xcstbor( &mainOpts);
528 xerrmes( &mainOpts);
529 xessent( &mainOpts);
530 xfactor( &mainOpts);
531 xinform( &mainOpts);
532 xnew ( &mainOpts);
533 xoldcop( &mainOpts);
534 xpermgr( &mainOpts);
535 xpermut( &mainOpts);
536 xprimes( &mainOpts);
537 xrandgr( &mainOpts);
538 xrandsc( &mainOpts);
539 xreadgr( &mainOpts);
540 xrelato( &mainOpts);
541 xstcs ( &mainOpts);
542 xstorag( &mainOpts);
543 xtoken ( &mainOpts);
544 xutil ( &mainOpts);
545 }
546
547
548 /*-------------------------- informGenerateTime ----------------------------*/
549
informGenerateTime(clock_t startTime,clock_t randSchrTime,clock_t optGroupTime,clock_t stcsTime)550 static void informGenerateTime(
551 clock_t startTime,
552 clock_t randSchrTime,
553 clock_t optGroupTime,
554 clock_t stcsTime)
555 {
556 clock_t totalTime;
557 #ifdef NOFLOAT
558 unsigned long secs, hSecs;
559 #endif
560
561 stcsTime -= optGroupTime;
562 optGroupTime -= randSchrTime;
563 randSchrTime -= startTime;
564 totalTime = randSchrTime + optGroupTime + stcsTime;
565
566 #ifndef NOFLOAT
567 printf( "\nTime: Random Schreier: %6.2lf sec",
568 (double) randSchrTime / CLK_TCK);
569 printf( "\n Gen optimization: %6.2lf sec",
570 (double) optGroupTime / CLK_TCK);
571 printf( "\n Schr-Todd-Cox-Sims: %6.2lf sec",
572 (double) stcsTime / CLK_TCK);
573 printf( "\n TOTAL: %6.2lf sec",
574 (double) totalTime / CLK_TCK);
575 #endif
576
577 #ifdef NOFLOAT
578 secs = randSchrTime / CLK_TCK;
579 hSecs = (randSchrTime - secs * CLK_TCK) * 100;
580 hSecs /= CLK_TCK;
581 printf( "\nTime: Random Schreier: %4lu.%02lu sec", secs, hSecs);
582 secs = optGroupTime / CLK_TCK;
583 hSecs = (optGroupTime - secs * CLK_TCK) * 100;
584 hSecs /= CLK_TCK;
585 printf( "\n Gen optimization: %4lu.%02lu sec", secs, hSecs);
586 secs = stcsTime / CLK_TCK;
587 hSecs = (stcsTime - secs * CLK_TCK) * 100;
588 hSecs /= CLK_TCK;
589 printf( "\n Schr-Todd-Cox-Sims: %4lu.%02lu sec", secs, hSecs);
590 secs = totalTime / CLK_TCK;
591 hSecs = (totalTime - secs * CLK_TCK) * 100;
592 hSecs /= CLK_TCK;
593 printf( "\n TOTAL: %4lu.%02lu sec", secs, hSecs);
594 #endif
595
596 printf( "\n");
597 }
598