Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@272 cc03376c-175c-47c8-b038-4cd826a8556b
857 lines
26 KiB
C
857 lines
26 KiB
C
/*
|
|
** Queens.c -- Find solutions to the Eight-Queens chess problem.
|
|
** Roberto Sierra 7/25/93 Version 1.1
|
|
** 3/19/84 Version 1.0
|
|
**
|
|
** Description:
|
|
** This program finds all the possible ways that N queens can
|
|
** be placed on an NxN chessboard so that the queens cannot
|
|
** capture one another -- that is, so that no rank, file or
|
|
** diagonal is occupied by more than one queen. By default,
|
|
** the program prints the first solution it finds. You can
|
|
** use the -a option to print all solutions, or the -c option
|
|
** just to count them. The program allows the chess board
|
|
** to be from 1x1 (trivial case) to 100x100. Warning: the
|
|
** larger the chess board, the longer it typically takes to
|
|
** find each solution, even though there may be more of them.
|
|
**
|
|
** This is a terrific example of the utility of recursion. The
|
|
** algorithm uses recursion to drastically limit the number
|
|
** of board positions that are tested. The program is able
|
|
** to find all 8x8 queen solutions in a fraction of a second
|
|
** (not counting print time). The code makes no attempt to
|
|
** eliminate symmetrical solutions, so the number of solutions
|
|
** reported will always be higher than the actual number of
|
|
** distinct solutions.
|
|
**
|
|
**
|
|
** Usage:
|
|
** Queens [-ac] n
|
|
**
|
|
** n number of queens (rows and columns).
|
|
** An integer from 1 to 100.
|
|
** -a Find (and print) all solutions.
|
|
** -c Count all solutions, but do not print them.
|
|
**
|
|
** The output is sent to stdout. All errors messages are
|
|
** sent to stderr. If a problem arises, the return code is -1.
|
|
**
|
|
**
|
|
** Examples:
|
|
**
|
|
** Queens 8 ## Show an 8x8 solution
|
|
** 8 queens on a 8x8 board...
|
|
** Q - - - - - - -
|
|
** - - - - Q - - -
|
|
** - - - - - - - Q
|
|
** - - - - - Q - -
|
|
** - - Q - - - - -
|
|
** - - - - - - Q -
|
|
** - Q - - - - - -
|
|
** - - - Q - - - -
|
|
**
|
|
** Queens -c 8 ## Count all 8x8 solutions
|
|
** 8 queens on a 8x8 board...
|
|
** ...there are 92 solutions.
|
|
**
|
|
** Queens -a 4 ## Show all 4x4 solutions
|
|
** 4 queens on a 4x4 board...
|
|
**
|
|
** Solution #1:
|
|
** - Q - -
|
|
** - - - Q
|
|
** Q - - -
|
|
** - - Q -
|
|
**
|
|
** Solution #2:
|
|
** - - Q -
|
|
** Q - - -
|
|
** - - - Q
|
|
** - Q - -
|
|
**
|
|
** ...there are 2 solutions.
|
|
**
|
|
**
|
|
** Build Instructions:
|
|
** You'll need an ANSI C compiler (or the willingness to edit
|
|
** the program a bit). If you've got Gnu C, then you can
|
|
** compile and load the program as follows:
|
|
**
|
|
** gcc Queens.c -ansi -o Queens
|
|
**
|
|
** [If you're using MPW on the Mac, define '-d MPW' on the
|
|
** compile line so that background processing will occur.]
|
|
**
|
|
**
|
|
** Algorithm:
|
|
** In a 1984 Byte article, I ran across an interesting letter
|
|
** from a high school student who was attempting to solve the
|
|
** Eight Queens problem using a BASIC interpreter. He had
|
|
** developed a program which placed eight queens successively
|
|
** on all sixty-four squares, testing for conflicts at each
|
|
** iteration. Of course, such a program would require 64^8
|
|
** iterations (about 2.8x10^14 iterations). Even in C on a,
|
|
** fast CPU, this could take months or years. Byte's answer was
|
|
** to alter the loops so that the queens resided on separate
|
|
** ranks, thereby reducing the number of iterations required
|
|
** to find all solutions to 8^8 iterations (about 16 million).
|
|
** More reasonable, but still requiring a chunk of CPU time.
|
|
**
|
|
** I puzzled about this problem a bit, and came to realize that
|
|
** this was still wasting a lot of CPU cycles. Though I'm sure
|
|
** others have come up with good algorithms, I decided to come
|
|
** up with my own, with a particular eye on efficiency. The
|
|
** resulting algorithm finds all 8x8 solutions in a fraction
|
|
** of a second (there are 92 solutions, including rotations).
|
|
** On a Sun 4, it'll find all 365,596 solutions on a 14x14 board
|
|
** in a bit over 2 minutes (printing them out requires extra
|
|
** time, of course). Even Byte's solution would require 14^14
|
|
** iterations (about 10^16) which would take aeons.
|
|
**
|
|
** My algorithm works as follows:
|
|
** (1) Place a queen in the top left corner.
|
|
** (2) Place another queen immediately below.
|
|
** (3) Test for conflicts. If the second queen conflicts (it
|
|
** does at first), then move it one square to the right.
|
|
** (4) Loop step 3 until there are no conflicts. Place
|
|
** the next queen on the board and recurse.
|
|
** (5) If any queen reaches the right edge of the board,
|
|
** remove it and 'pop' to the previous recursion level.
|
|
** (6) Now repeat these steps recursively until all eight
|
|
** queens (or however many) have been placed without
|
|
** conflict -- the result is a solution to the problem,
|
|
** which is counted and optionally printed.
|
|
**
|
|
** Because conflicts are tested as the recursion proceeds,
|
|
** this has the effect of 'pruning' the recursion so that
|
|
** a large number of board positions are not even attempted.
|
|
** The result is that the algorithm runs in reasonable time.
|
|
**
|
|
** I used a few tricks to make the test-for-conflict code
|
|
** extremely efficient -- there is no 'inner' loop to search
|
|
** along ranks, files, or diagonals. A series of arrays are
|
|
** maintained instead which indicate which queen currently
|
|
** 'owns' each rank, file or diagonal. This makes the
|
|
** algorithm really fly, though the code is a little hard to
|
|
** read. Lastly, pointer arithmetic is used to reduce the
|
|
** number of implicit multiplications used in array addressing.
|
|
**
|
|
**
|
|
** Contact:
|
|
** For queries regarding this program, contact Roberto Sierra
|
|
** at any of the following addresses:
|
|
**
|
|
** Roberto Sierra
|
|
** bert@netcom.com (preferred address)
|
|
** 73557.2101@compuserve.com
|
|
**
|
|
** Tempered MicroDesigns
|
|
** P.O. Box 170638
|
|
** San Francisco, CA 94117
|
|
**
|
|
**
|
|
** Fine Print:
|
|
** This program is in the public domain and can be used for
|
|
** any purpose whatsoever, including commercial application.
|
|
** [I'd like to hear what you do with it, though.]
|
|
** Absolutely no warranty or liability is implied or extended
|
|
** by the author.
|
|
**
|
|
**
|
|
** Modification History:
|
|
** PRS 3/19/84 v1.0 -- Original version.
|
|
** PRS 7/25/93 v1.1 -- ANSIfied the code. More efficient pointers.
|
|
**
|
|
*/
|
|
|
|
/***************************************************************/
|
|
/* Timer options. You MUST uncomment one of the options below */
|
|
/* or compile, for example, with the '-DUNIX' option. */
|
|
/***************************************************************/
|
|
/* #define Amiga */
|
|
/* #define UNIX */
|
|
/* #define UNIX_Old */
|
|
/* #define VMS */
|
|
/* #define BORLAND_C */
|
|
/* #define MSC */
|
|
/* #define MAC */
|
|
/* #define IPSC */
|
|
/* #define FORTRAN_SEC */
|
|
/* #define GTODay */
|
|
/* #define CTimer */
|
|
/* #define UXPM */
|
|
/* #define MAC_TMgr */
|
|
/* #define PARIX */
|
|
/* #define POSIX */
|
|
/* #define WIN32 */
|
|
/* #define POSIX1 */
|
|
/***********************/
|
|
|
|
#include <stdio.h> /* Need standard I/O functions */
|
|
#include <stdlib.h> /* Need exit() routine interface */
|
|
#include <string.h> /* Need strcmp() interface */
|
|
#ifdef MPW /* Macintosh MPW ONLY */
|
|
#include <CursorCtl.h> /* Need cursor control interfaces */
|
|
#endif
|
|
|
|
#define MAXQUEENS 100 /* Maximum number of queens */
|
|
#define MAXRANKS MAXQUEENS /* Maximum number of ranks (rows) */
|
|
#define MAXFILES MAXQUEENS /* Maximum number of files (columns) */
|
|
#define MAXDIAGS (MAXRANKS+MAXFILES-1) /* Maximum number of diagonals */
|
|
#define EMPTY (MAXQUEENS+1) /* Marks unoccupied file or diagonal */
|
|
|
|
/* GLOBAL VARIABLES */
|
|
|
|
int queens; /* Number of queens to place */
|
|
int ranks; /* Number of ranks (rows) */
|
|
int files; /* Number of files (columns) */
|
|
int printing = 1; /* TRUE if printing positions */
|
|
int findall = 0; /* TRUE if finding all solutions */
|
|
|
|
unsigned long solutions = 0; /* Number of solutions found */
|
|
int queen[MAXRANKS]; /* File on which each queen is located */
|
|
int file[MAXFILES]; /* Which queen 'owns' each file */
|
|
int fordiag[MAXDIAGS]; /* Which queen 'owns' forward diagonals */
|
|
int bakdiag[MAXDIAGS]; /* Which queen 'owns' reverse diagonals */
|
|
char *progname = 0; /* The name of this program */
|
|
|
|
|
|
|
|
|
|
|
|
/***********************/
|
|
/**** ROUTINES ****/
|
|
/***********************/
|
|
|
|
/* Internal prototypes */
|
|
//void main(int argc,char **argv); /* Main program */
|
|
void find(int level); /* Algorithm to find solutions */
|
|
void pboard(void); /* Print a solution */
|
|
void run_queens(int argc,char **argv);
|
|
|
|
|
|
|
|
|
|
/*---------------------- main() ---------------------------
|
|
** MAIN program. The main purpose of this routine is
|
|
** to deal with decoding the command line arguments,
|
|
** initializing the various arrays, and starting the
|
|
** recursive search routine.
|
|
*/
|
|
int main(void)
|
|
{
|
|
char *args[] = {"queens", "-c", "12"};
|
|
run_queens(3, args);
|
|
}
|
|
|
|
void run_queens(int argc,char **argv)
|
|
{
|
|
register int i; /* Loop variable */
|
|
register char *p; /* Pointer to argument */
|
|
double starttime, benchtime, dtime();
|
|
|
|
#ifdef MPW /* Macintosh MPW ONLY */
|
|
InitCursorCtl(0); /* Enable cursor control */
|
|
#endif
|
|
|
|
progname = argv[0]; /* The name of the program */
|
|
|
|
/**** DECODE COMMAND LINE ARGUMENTS ****/
|
|
|
|
for (i=1; i<argc; ++i) { /* Scan through arguments */
|
|
p = argv[i]; /* Pointer to base of argument */
|
|
if (*p == '-') { /* Command line option? */
|
|
while (*++p) { /* Loop through characters */
|
|
switch (*p) { /* What is the character */
|
|
case 'a': /* '-a' option */
|
|
findall = 1; /* Set flag to find all solutions */
|
|
break;
|
|
case 'c': /* '-c' option */
|
|
printing = 0; /* Counting, not printing */
|
|
findall = 1; /* Also forces findall option */
|
|
break;
|
|
default: /* Illegal option */
|
|
fprintf(stderr,"%s: Illegal option '%s'\n",progname,argv[i]);
|
|
fprintf(stderr,"usage: %s [-ac] queens\n",progname);
|
|
exit(-1);
|
|
} /* End of switch */
|
|
} /* End of loop */
|
|
} else { /* End of option test */
|
|
if (sscanf(p,"%d",&queens) != 1) { /* Read integer argument */
|
|
fprintf(stderr,"%s: non-integer argument '%s'\n",progname,p);
|
|
exit(-1);
|
|
}
|
|
if (queens <= 0) { /* N must be positive */
|
|
fprintf(stderr,"%s: queens must be positive integer\n",progname);
|
|
exit(-1);
|
|
}
|
|
if (queens > MAXQUEENS) { /* N can't be too large */
|
|
fprintf(stderr,"%s: can't have more than %d queens\n",
|
|
progname, MAXQUEENS);
|
|
exit(-1);
|
|
}
|
|
} /* End of argument test */
|
|
} /* End of argument scan loop */
|
|
if (queens == 0) {
|
|
fprintf(stderr,"%s: missing queens argument\n",progname);
|
|
fprintf(stderr,"usage: %s [-ac] queens\n",progname);
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
ranks = files = queens; /* NxN board for N queens */
|
|
printf("%d queen%s on a %dx%d board...\n",
|
|
queens, queens>1? "s" : "", ranks, files);
|
|
fflush(stdout);
|
|
|
|
starttime = dtime();
|
|
|
|
/* Initialization */
|
|
solutions = 0; /* No solutions yet */
|
|
for (i=0; i<MAXFILES; ++i) file[i] = EMPTY;
|
|
for (i=0; i<MAXDIAGS; ++i) fordiag[i] = bakdiag[i] = EMPTY;
|
|
|
|
/* Find all solutions (begin recursion) */
|
|
find(0);
|
|
if (printing && solutions) putchar('\n');
|
|
|
|
/* Report results */
|
|
if (solutions == 1) {
|
|
printf("...there is 1 solution\n");
|
|
} else {
|
|
printf("...there are %ld solutions\n", solutions);
|
|
}
|
|
|
|
benchtime = dtime() - starttime;
|
|
printf("Run Time (sec) = %9.3lf\n\n",benchtime);
|
|
|
|
|
|
exit(0); /* No errors */
|
|
} /* End of main() */
|
|
|
|
|
|
|
|
/*-------------------------- find() ----------------------------
|
|
** FIND is the recursive heart of the program, and finds all
|
|
** solutions given a set of level-1 fixed queen positions.
|
|
** The routine moves a single queen through all files (columns)
|
|
** at the current rank (recursion level). As the queen is moved,
|
|
** conflict tests are made. If the queen can be placed without
|
|
** conflict, then the routine recurses to the next level. When
|
|
** all queens have been placed without conflict, a solution is
|
|
** counted and reported.
|
|
*/
|
|
|
|
void find(register int level)
|
|
{
|
|
register int f; /* Indexes through files */
|
|
register int *fp,*fdp,*bdp; /* Ptrs to file/diagonal entries */
|
|
|
|
#ifdef MPW /* Macintosh MPW ONLY */
|
|
if (level & 7 == 0) { /* Periodically break for... */
|
|
SpinCursor(1); /* background processing */
|
|
}
|
|
#endif
|
|
|
|
if (level == queens) { /* Placed all queens? Stop. */
|
|
++solutions; /* Congrats, this is a solution! */
|
|
if (printing) pboard(); /* Print board if printing */
|
|
if (!findall) exit(0); /* May stop after first solution */
|
|
#ifdef MPW /* Macintosh MPW ONLY */
|
|
SpinCursor(1); /* Allow background processing */
|
|
#endif
|
|
} else { /* Not at final level yet */
|
|
|
|
for ( /* MOVE QUEEN THROUGH ALL FILES */
|
|
f = 0, /* Queen starts at left (file 0) */
|
|
fp = file, /* Ptr to base of file array */
|
|
fdp = &fordiag[level], /* Ptr to first fwd diag entry */
|
|
bdp = &bakdiag[level+files-1] /* Ptr to first bak diag entry */
|
|
;
|
|
f < files /* Loop through all files */
|
|
;
|
|
++f, /* Advance index */
|
|
++fp, ++fdp, --bdp /* Advance pointers */
|
|
) {
|
|
if (*fp >= level && /* No queen on the file? */
|
|
*fdp >= level && *bdp >= level /* No queens on diagonals? */
|
|
) {
|
|
queen[level] = f; /* Note new position of queen */
|
|
*fp = *fdp = *bdp = level; /* Place queen on file & diags */
|
|
find(level+1); /* This level OK, recurse to next */
|
|
*fp = *fdp = *bdp = EMPTY; /* Remove queen from file & diags */
|
|
} /* End of conflict test */
|
|
} /* End of file loop */
|
|
} /* End if (level == queens) */
|
|
} /* End of find() */
|
|
|
|
|
|
|
|
|
|
/*------------------------- pboard() -----------------------
|
|
** This routines prints the board for a particular solution.
|
|
** The output is sent to stdout.
|
|
*/
|
|
|
|
void pboard(void)
|
|
{
|
|
register int i,j; /* Rank/File indices */
|
|
|
|
if (findall) { /* Only if searching for all */
|
|
printf("\nSolution #%lu:\n",solutions); /* Print solution number */
|
|
}
|
|
for (i=0; i<ranks; ++i) { /* Loop through all ranks */
|
|
for (j=0; j<files; ++j) { /* Loop through all files */
|
|
putchar(' '); /* Output a space */
|
|
if (j==queen[i]) putchar('Q'); /* Output Q for queen... */
|
|
else putchar('-'); /* or '-' if empty */
|
|
}
|
|
putchar('\n'); /* Break line */
|
|
}
|
|
fflush(stdout); /* Flush solution to output */
|
|
} /* End of pboard() */
|
|
|
|
/*****************************************************/
|
|
/* Various timer routines. */
|
|
/* Al Aburto, aburto@nosc.mil, 18 Feb 1997 */
|
|
/* */
|
|
/* t = dtime() outputs the current time in seconds. */
|
|
/* Use CAUTION as some of these routines will mess */
|
|
/* up when timing across the hour mark!!! */
|
|
/* */
|
|
/* For timing I use the 'user' time whenever */
|
|
/* possible. Using 'user+sys' time is a separate */
|
|
/* issue. */
|
|
/* */
|
|
/* Example Usage: */
|
|
/* [timer options added here] */
|
|
/* main() */
|
|
/* { */
|
|
/* double starttime,benchtime,dtime(); */
|
|
/* */
|
|
/* starttime = dtime(); */
|
|
/* [routine to time] */
|
|
/* benchtime = dtime() - starttime; */
|
|
/* } */
|
|
/* */
|
|
/* [timer code below added here] */
|
|
/*****************************************************/
|
|
|
|
/*********************************/
|
|
/* Timer code. */
|
|
/*********************************/
|
|
/*******************/
|
|
/* Amiga dtime() */
|
|
/*******************/
|
|
#ifdef Amiga
|
|
#include <ctype.h>
|
|
#define HZ 50
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
struct tt
|
|
{
|
|
long days;
|
|
long minutes;
|
|
long ticks;
|
|
} tt;
|
|
|
|
DateStamp(&tt);
|
|
|
|
q = ((double)(tt.ticks + (tt.minutes * 60L * 50L))) / (double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************/
|
|
/* UNIX dtime(). This is the preferred UNIX timer. */
|
|
/* Provided by: Markku Kolkka, mk59200@cc.tut.fi */
|
|
/* HP-UX Addition by: Bo Thide', bt@irfu.se */
|
|
/*****************************************************/
|
|
#ifdef UNIX
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
|
|
#ifdef hpux
|
|
#include <sys/syscall.h>
|
|
#define getrusage(a,b) syscall(SYS_getrusage,a,b)
|
|
#endif
|
|
|
|
struct rusage rusage;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
getrusage(RUSAGE_SELF,&rusage);
|
|
|
|
q = (double)(rusage.ru_utime.tv_sec);
|
|
q = q + (double)(rusage.ru_utime.tv_usec) * 1.0e-06;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/***************************************************/
|
|
/* UNIX_Old dtime(). This is the old UNIX timer. */
|
|
/* Make sure HZ is properly defined in param.h !! */
|
|
/***************************************************/
|
|
#ifdef UNIX_Old
|
|
#include <sys/types.h>
|
|
#include <sys/times.h>
|
|
#include <sys/param.h>
|
|
|
|
#ifndef HZ
|
|
#define HZ 60
|
|
#endif
|
|
|
|
struct tms tms;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
times(&tms);
|
|
|
|
q = (double)(tms.tms_utime) / (double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*********************************************************/
|
|
/* VMS dtime() for VMS systems. */
|
|
/* Provided by: RAMO@uvphys.phys.UVic.CA */
|
|
/* Some people have run into problems with this timer. */
|
|
/*********************************************************/
|
|
#ifdef VMS
|
|
#include time
|
|
|
|
#ifndef HZ
|
|
#define HZ 100
|
|
#endif
|
|
|
|
struct tbuffer_t
|
|
{
|
|
int proc_user_time;
|
|
int proc_system_time;
|
|
int child_user_time;
|
|
int child_system_time;
|
|
};
|
|
|
|
struct tbuffer_t tms;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
times(&tms);
|
|
|
|
q = (double)(tms.proc_user_time) / (double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/******************************/
|
|
/* BORLAND C dtime() for DOS */
|
|
/******************************/
|
|
#ifdef BORLAND_C
|
|
#include <ctype.h>
|
|
#include <dos.h>
|
|
#include <time.h>
|
|
|
|
#define HZ 100
|
|
struct time tnow;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
gettime(&tnow);
|
|
|
|
q = 60.0 * (double)(tnow.ti_min);
|
|
q = q + (double)(tnow.ti_sec);
|
|
q = q + (double)(tnow.ti_hund)/(double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/**************************************/
|
|
/* Microsoft C (MSC) dtime() for DOS */
|
|
/**************************************/
|
|
#ifdef MSC
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
|
|
#define HZ CLOCKS_PER_SEC
|
|
clock_t tnow;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
tnow = clock();
|
|
|
|
q = (double)tnow / (double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*************************************/
|
|
/* Macintosh (MAC) Think C dtime() */
|
|
/*************************************/
|
|
#ifdef MAC
|
|
#include <time.h>
|
|
|
|
#define HZ 60
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
q = (double)clock() / (double)HZ;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/************************************************************/
|
|
/* iPSC/860 (IPSC) dtime() for i860. */
|
|
/* Provided by: Dan Yergeau, yergeau@gloworm.Stanford.EDU */
|
|
/************************************************************/
|
|
#ifdef IPSC
|
|
extern double dclock();
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
q = dclock();
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/**************************************************/
|
|
/* FORTRAN dtime() for Cray type systems. */
|
|
/* This is the preferred timer for Cray systems. */
|
|
/**************************************************/
|
|
#ifdef FORTRAN_SEC
|
|
|
|
fortran double second();
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
second(&q);
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************/
|
|
/* UNICOS C dtime() for Cray UNICOS systems. Don't use */
|
|
/* unless absolutely necessary as returned time includes */
|
|
/* 'user+system' time. Provided by: R. Mike Dority, */
|
|
/* dority@craysea.cray.com */
|
|
/***********************************************************/
|
|
#ifdef CTimer
|
|
#include <time.h>
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
clock_t clock(void);
|
|
|
|
q = (double)clock() / (double)CLOCKS_PER_SEC;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/********************************************/
|
|
/* Another UNIX timer using gettimeofday(). */
|
|
/* However, getrusage() is preferred. */
|
|
/********************************************/
|
|
#ifdef GTODay
|
|
#include <sys/time.h>
|
|
|
|
struct timeval tnow;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
gettimeofday(&tnow,NULL);
|
|
q = (double)tnow.tv_sec + (double)tnow.tv_usec * 1.0e-6;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************/
|
|
/* Fujitsu UXP/M timer. */
|
|
/* Provided by: Mathew Lim, ANUSF, M.Lim@anu.edu.au */
|
|
/*****************************************************/
|
|
#ifdef UXPM
|
|
#include <sys/types.h>
|
|
#include <sys/timesu.h>
|
|
struct tmsu rusage;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
timesu(&rusage);
|
|
|
|
q = (double)(rusage.tms_utime) * 1.0e-06;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/**********************************************/
|
|
/* Macintosh (MAC_TMgr) Think C dtime() */
|
|
/* requires Think C Language Extensions or */
|
|
/* #include <MacHeaders> in the prefix */
|
|
/* provided by Francis H Schiffer 3rd (fhs) */
|
|
/* skipschiffer@genie.geis.com */
|
|
/**********************************************/
|
|
#ifdef MAC_TMgr
|
|
#include <Timer.h>
|
|
#include <stdlib.h>
|
|
|
|
static TMTask mgrTimer;
|
|
static Boolean mgrInited = false;
|
|
static double mgrClock;
|
|
|
|
#define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer )
|
|
#define MAX_TIME 1800000000L
|
|
/* MAX_TIME limits time between calls to */
|
|
/* dtime( ) to no more than 30 minutes */
|
|
/* this limitation could be removed by */
|
|
/* creating a completion routine to sum */
|
|
/* 30 minute segments (fhs 1994 feb 9) */
|
|
|
|
static void Remove_timer( )
|
|
{
|
|
RMV_TIMER;
|
|
mgrInited = false;
|
|
}
|
|
|
|
double dtime( )
|
|
{
|
|
if( mgrInited ) {
|
|
RMV_TIMER;
|
|
mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6;
|
|
} else {
|
|
if( _atexit( &Remove_timer ) == 0 ) mgrInited = true;
|
|
mgrClock = 0.0;
|
|
}
|
|
|
|
if ( mgrInited )
|
|
{
|
|
mgrTimer.tmAddr = NULL;
|
|
mgrTimer.tmCount = 0;
|
|
mgrTimer.tmWakeUp = 0;
|
|
mgrTimer.tmReserved = 0;
|
|
InsTime( (QElemPtr)&mgrTimer );
|
|
PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME );
|
|
}
|
|
return( mgrClock );
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************/
|
|
/* Parsytec GCel timer. */
|
|
/* Provided by: Georg Wambach, gw@informatik.uni-koeln.de */
|
|
/***********************************************************/
|
|
#ifdef PARIX
|
|
#include <sys/time.h>
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
q = (double) (TimeNowHigh()) / (double) CLK_TCK_HIGH;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/************************************************/
|
|
/* Sun Solaris POSIX dtime() routine */
|
|
/* Provided by: Case Larsen, CTLarsen.lbl.gov */
|
|
/************************************************/
|
|
#ifdef POSIX
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/rusage.h>
|
|
|
|
#ifdef __hpux
|
|
#include <sys/syscall.h>
|
|
#endif
|
|
|
|
struct rusage rusage;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
|
|
getrusage(RUSAGE_SELF,&rusage);
|
|
|
|
q = (double)(rusage.ru_utime.tv_sec);
|
|
q = q + (double)(rusage.ru_utime.tv_nsec) * 1.0e-09;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
|
|
/****************************************************/
|
|
/* Windows NT (32 bit) dtime() routine */
|
|
/* Provided by: Piers Haken, piersh@microsoft.com */
|
|
/****************************************************/
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
|
|
double dtime(void)
|
|
{
|
|
double q;
|
|
|
|
q = (double)GetTickCount() * 1.0e-03;
|
|
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************/
|
|
/* Time according to POSIX.1 - <J.Pelan@qub.ac.uk> */
|
|
/* Ref: "POSIX Programmer's Guide" O'Reilly & Assoc.*/
|
|
/*****************************************************/
|
|
#ifdef POSIX1
|
|
#define _POSIX_SOURCE 1
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
#include <sys/times.h>
|
|
|
|
struct tms tms;
|
|
|
|
double dtime()
|
|
{
|
|
double q;
|
|
times(&tms);
|
|
q = (double)tms.tms_utime / (double)CLK_TCK;
|
|
return q;
|
|
}
|
|
#endif
|
|
|
|
/*-------- End of queens.c, Say goodnight Linda! --------*/
|