/* ZSolveMain.c - A very fast Sudoku solver

Version 1.0 of April 4, 2013

Copyright © 2009-2013, Jason T. Linhart
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
	•	Redistributions of source code must retain the above copyright notice,
		this list of conditions and the following disclaimer.
	•	Redistributions in binary form must reproduce the above copyright
		notice, this list of conditions and the following disclaimer in the
		documentation and/or other materials provided with the distribution.
	•	Neither the name Jason T. Linhart nor the names of other contributors
		may be used to endorse or promote products derived from this software
		without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	ZSolver.c
	Based on code posted to <http://forum.enjoysudoku.com/
						3-77us-solver-2-8g-cpu-testcase-17sodoku-t30470.html>
	by user zhouyundong_2012.
	Some versions of the code include the message:
	"Good Luck! Shanghai China 2012/3/14 Zhou Yun Dong"
	The copyright is not specified.
*/

#include <string.h>		// JTL
#include <ctype.h>		// JTL
#include <stdio.h>
#if defined(_WIN32) || defined(_WINDOWS)
#include <time.h>
#else
#include <sys/resource.h>
#endif // Windows

/*
	Good Luck! Shanghai China 2012/3/14 Zhou Yun Dong
*/

// Taken from ZSolver.h

typedef unsigned char byte;
typedef unsigned short word;			// JTL
//typedef int bool;						// JTL
#ifndef true
#define false			0
#define true			1
#endif

//High, Middle, Low 9 bit of a 27-bit number
#define HIGH_9_BIT(v)		(((v) >> 18) & 0x1FF)
#define MID_9_BIT(v)		(((v) >> 9) & 0x1FF)
#define LOW_9_BIT(v)		((v) & 0x1FF)

#define FULL_TO_COLUMN(v)	(((v) | ((v) >> 9) | ((v) >> 18)) & 0x1FF)
// Full Mask(27-bit) to 9 bit

#define FULL_TO_SHRINK(v)	(TblShrinkMask[(v) & 0x1FF] | \
							TblShrinkMask[((v) >> 9) & 0x1FF] << 3 | \
							TblShrinkMask[((v) >> 18) & 0x1FF] << 6)

#define BIT_SET_27			0x07FFFFFF
#define BIT_SET_30			0x3FFFFFFF

#define NORF(n)				F[n] &= BlockMaskSum[n % 3] ^ BlockMask[n];
#define SAVF(n)				G[Index].F[n] = F[n];
#define RESF(n)				CompF[n] = F[n] = G[Index].F[n];
#define AN(v, n)			(v) &= (n);

typedef struct CGame
{
//public:
	int		F[27]; //30-bit Full Mask
	int		Block; //The Block Number of guess [0, 27)
	int		Mask; //The 9-bit Mask of guess
	int		Left; //The 9-bit Left Mask of guess
} CGame;

// End of code taken from ZSolver.h

// Derived from tbl.c

int TblMult3[9] =
{
	0x0,	0x3,	0x6,	0x9,	0xC,	0xF,	0x12,	0x15,	0x18
};

int TblMult9[9] =
{
	0x0,	0x9,	0x12,	0x1B,	0x24,	0x2D,	0x36,	0x3F,	0x48
};

int TblCombineMask[512] =
{
	0x7FFFFFF,	0x7FBFDFE,	0x7F7FBFD,	0x7F3F9FC,	0x7EFF7FB,	0x7EBF5FA,	0x7E7F3F9,	0x7E3F1F8,
	0x7DFEFF7,	0x7DBEDF6,	0x7D7EBF5,	0x7D3E9F4,	0x7CFE7F3,	0x7CBE5F2,	0x7C7E3F1,	0x7C3E1F0,
	0x7BFDFEF,	0x7BBDDEE,	0x7B7DBED,	0x7B3D9EC,	0x7AFD7EB,	0x7ABD5EA,	0x7A7D3E9,	0x7A3D1E8,
	0x79FCFE7,	0x79BCDE6,	0x797CBE5,	0x793C9E4,	0x78FC7E3,	0x78BC5E2,	0x787C3E1,	0x783C1E0,
	0x77FBFDF,	0x77BBDDE,	0x777BBDD,	0x773B9DC,	0x76FB7DB,	0x76BB5DA,	0x767B3D9,	0x763B1D8,
	0x75FAFD7,	0x75BADD6,	0x757ABD5,	0x753A9D4,	0x74FA7D3,	0x74BA5D2,	0x747A3D1,	0x743A1D0,
	0x73F9FCF,	0x73B9DCE,	0x7379BCD,	0x73399CC,	0x72F97CB,	0x72B95CA,	0x72793C9,	0x72391C8,
	0x71F8FC7,	0x71B8DC6,	0x7178BC5,	0x71389C4,	0x70F87C3,	0x70B85C2,	0x70783C1,	0x70381C0,
	0x6FF7FBF,	0x6FB7DBE,	0x6F77BBD,	0x6F379BC,	0x6EF77BB,	0x6EB75BA,	0x6E773B9,	0x6E371B8,
	0x6DF6FB7,	0x6DB6DB6,	0x6D76BB5,	0x6D369B4,	0x6CF67B3,	0x6CB65B2,	0x6C763B1,	0x6C361B0,
	0x6BF5FAF,	0x6BB5DAE,	0x6B75BAD,	0x6B359AC,	0x6AF57AB,	0x6AB55AA,	0x6A753A9,	0x6A351A8,
	0x69F4FA7,	0x69B4DA6,	0x6974BA5,	0x69349A4,	0x68F47A3,	0x68B45A2,	0x68743A1,	0x68341A0,
	0x67F3F9F,	0x67B3D9E,	0x6773B9D,	0x673399C,	0x66F379B,	0x66B359A,	0x6673399,	0x6633198,
	0x65F2F97,	0x65B2D96,	0x6572B95,	0x6532994,	0x64F2793,	0x64B2592,	0x6472391,	0x6432190,
	0x63F1F8F,	0x63B1D8E,	0x6371B8D,	0x633198C,	0x62F178B,	0x62B158A,	0x6271389,	0x6231188,
	0x61F0F87,	0x61B0D86,	0x6170B85,	0x6130984,	0x60F0783,	0x60B0582,	0x6070381,	0x6030180,
	0x5FEFF7F,	0x5FAFD7E,	0x5F6FB7D,	0x5F2F97C,	0x5EEF77B,	0x5EAF57A,	0x5E6F379,	0x5E2F178,
	0x5DEEF77,	0x5DAED76,	0x5D6EB75,	0x5D2E974,	0x5CEE773,	0x5CAE572,	0x5C6E371,	0x5C2E170,
	0x5BEDF6F,	0x5BADD6E,	0x5B6DB6D,	0x5B2D96C,	0x5AED76B,	0x5AAD56A,	0x5A6D369,	0x5A2D168,
	0x59ECF67,	0x59ACD66,	0x596CB65,	0x592C964,	0x58EC763,	0x58AC562,	0x586C361,	0x582C160,
	0x57EBF5F,	0x57ABD5E,	0x576BB5D,	0x572B95C,	0x56EB75B,	0x56AB55A,	0x566B359,	0x562B158,
	0x55EAF57,	0x55AAD56,	0x556AB55,	0x552A954,	0x54EA753,	0x54AA552,	0x546A351,	0x542A150,
	0x53E9F4F,	0x53A9D4E,	0x5369B4D,	0x532994C,	0x52E974B,	0x52A954A,	0x5269349,	0x5229148,
	0x51E8F47,	0x51A8D46,	0x5168B45,	0x5128944,	0x50E8743,	0x50A8542,	0x5068341,	0x5028140,
	0x4FE7F3F,	0x4FA7D3E,	0x4F67B3D,	0x4F2793C,	0x4EE773B,	0x4EA753A,	0x4E67339,	0x4E27138,
	0x4DE6F37,	0x4DA6D36,	0x4D66B35,	0x4D26934,	0x4CE6733,	0x4CA6532,	0x4C66331,	0x4C26130,
	0x4BE5F2F,	0x4BA5D2E,	0x4B65B2D,	0x4B2592C,	0x4AE572B,	0x4AA552A,	0x4A65329,	0x4A25128,
	0x49E4F27,	0x49A4D26,	0x4964B25,	0x4924924,	0x48E4723,	0x48A4522,	0x4864321,	0x4824120,
	0x47E3F1F,	0x47A3D1E,	0x4763B1D,	0x472391C,	0x46E371B,	0x46A351A,	0x4663319,	0x4623118,
	0x45E2F17,	0x45A2D16,	0x4562B15,	0x4522914,	0x44E2713,	0x44A2512,	0x4462311,	0x4422110,
	0x43E1F0F,	0x43A1D0E,	0x4361B0D,	0x432190C,	0x42E170B,	0x42A150A,	0x4261309,	0x4221108,
	0x41E0F07,	0x41A0D06,	0x4160B05,	0x4120904,	0x40E0703,	0x40A0502,	0x4060301,	0x4020100,
	0x3FDFEFF,	0x3F9FCFE,	0x3F5FAFD,	0x3F1F8FC,	0x3EDF6FB,	0x3E9F4FA,	0x3E5F2F9,	0x3E1F0F8,
	0x3DDEEF7,	0x3D9ECF6,	0x3D5EAF5,	0x3D1E8F4,	0x3CDE6F3,	0x3C9E4F2,	0x3C5E2F1,	0x3C1E0F0,
	0x3BDDEEF,	0x3B9DCEE,	0x3B5DAED,	0x3B1D8EC,	0x3ADD6EB,	0x3A9D4EA,	0x3A5D2E9,	0x3A1D0E8,
	0x39DCEE7,	0x399CCE6,	0x395CAE5,	0x391C8E4,	0x38DC6E3,	0x389C4E2,	0x385C2E1,	0x381C0E0,
	0x37DBEDF,	0x379BCDE,	0x375BADD,	0x371B8DC,	0x36DB6DB,	0x369B4DA,	0x365B2D9,	0x361B0D8,
	0x35DAED7,	0x359ACD6,	0x355AAD5,	0x351A8D4,	0x34DA6D3,	0x349A4D2,	0x345A2D1,	0x341A0D0,
	0x33D9ECF,	0x3399CCE,	0x3359ACD,	0x33198CC,	0x32D96CB,	0x32994CA,	0x32592C9,	0x32190C8,
	0x31D8EC7,	0x3198CC6,	0x3158AC5,	0x31188C4,	0x30D86C3,	0x30984C2,	0x30582C1,	0x30180C0,
	0x2FD7EBF,	0x2F97CBE,	0x2F57ABD,	0x2F178BC,	0x2ED76BB,	0x2E974BA,	0x2E572B9,	0x2E170B8,
	0x2DD6EB7,	0x2D96CB6,	0x2D56AB5,	0x2D168B4,	0x2CD66B3,	0x2C964B2,	0x2C562B1,	0x2C160B0,
	0x2BD5EAF,	0x2B95CAE,	0x2B55AAD,	0x2B158AC,	0x2AD56AB,	0x2A954AA,	0x2A552A9,	0x2A150A8,
	0x29D4EA7,	0x2994CA6,	0x2954AA5,	0x29148A4,	0x28D46A3,	0x28944A2,	0x28542A1,	0x28140A0,
	0x27D3E9F,	0x2793C9E,	0x2753A9D,	0x271389C,	0x26D369B,	0x269349A,	0x2653299,	0x2613098,
	0x25D2E97,	0x2592C96,	0x2552A95,	0x2512894,	0x24D2693,	0x2492492,	0x2452291,	0x2412090,
	0x23D1E8F,	0x2391C8E,	0x2351A8D,	0x231188C,	0x22D168B,	0x229148A,	0x2251289,	0x2211088,
	0x21D0E87,	0x2190C86,	0x2150A85,	0x2110884,	0x20D0683,	0x2090482,	0x2050281,	0x2010080,
	0x1FCFE7F,	0x1F8FC7E,	0x1F4FA7D,	0x1F0F87C,	0x1ECF67B,	0x1E8F47A,	0x1E4F279,	0x1E0F078,
	0x1DCEE77,	0x1D8EC76,	0x1D4EA75,	0x1D0E874,	0x1CCE673,	0x1C8E472,	0x1C4E271,	0x1C0E070,
	0x1BCDE6F,	0x1B8DC6E,	0x1B4DA6D,	0x1B0D86C,	0x1ACD66B,	0x1A8D46A,	0x1A4D269,	0x1A0D068,
	0x19CCE67,	0x198CC66,	0x194CA65,	0x190C864,	0x18CC663,	0x188C462,	0x184C261,	0x180C060,
	0x17CBE5F,	0x178BC5E,	0x174BA5D,	0x170B85C,	0x16CB65B,	0x168B45A,	0x164B259,	0x160B058,
	0x15CAE57,	0x158AC56,	0x154AA55,	0x150A854,	0x14CA653,	0x148A452,	0x144A251,	0x140A050,
	0x13C9E4F,	0x1389C4E,	0x1349A4D,	0x130984C,	0x12C964B,	0x128944A,	0x1249249,	0x1209048,
	0x11C8E47,	0x1188C46,	0x1148A45,	0x1108844,	0x10C8643,	0x1088442,	0x1048241,	0x1008040,
	0xFC7E3F,	0xF87C3E,	0xF47A3D,	0xF0783C,	0xEC763B,	0xE8743A,	0xE47239,	0xE07038,
	0xDC6E37,	0xD86C36,	0xD46A35,	0xD06834,	0xCC6633,	0xC86432,	0xC46231,	0xC06030,
	0xBC5E2F,	0xB85C2E,	0xB45A2D,	0xB0582C,	0xAC562B,	0xA8542A,	0xA45229,	0xA05028,
	0x9C4E27,	0x984C26,	0x944A25,	0x904824,	0x8C4623,	0x884422,	0x844221,	0x804020,
	0x7C3E1F,	0x783C1E,	0x743A1D,	0x70381C,	0x6C361B,	0x68341A,	0x643219,	0x603018,
	0x5C2E17,	0x582C16,	0x542A15,	0x502814,	0x4C2613,	0x482412,	0x442211,	0x402010,
	0x3C1E0F,	0x381C0E,	0x341A0D,	0x30180C,	0x2C160B,	0x28140A,	0x241209,	0x201008,
	0x1C0E07,	0x180C06,	0x140A05,	0x100804,	0xC0603,	0x80402,	0x40201,	0x0
};

int TblNumberOne[512] =
{
	0x0,	0x1,	0x1,	0x2,	0x1,	0x2,	0x2,	0x3,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x1,	0x2,	0x2,	0x3,	0x2,	0x3,	0x3,	0x4,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x2,	0x3,	0x3,	0x4,	0x3,	0x4,	0x4,	0x5,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x3,	0x4,	0x4,	0x5,	0x4,	0x5,	0x5,	0x6,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x4,	0x5,	0x5,	0x6,	0x5,	0x6,	0x6,	0x7,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x5,	0x6,	0x6,	0x7,	0x6,	0x7,	0x7,	0x8,
	0x6,	0x7,	0x7,	0x8,	0x7,	0x8,	0x8,	0x9
};

int TblAnother1[27] =
{
	0x1,	0x0,	0x0,	0x4,	0x3,	0x3,	0x7,	0x6,	0x6,
	0xA,	0x9,	0x9,	0xD,	0xC,	0xC,	0x10,	0xF,	0xF,
	0x13,	0x12,	0x12,	0x16,	0x15,	0x15,	0x19,	0x18,	0x18
};

int TblAnother2[27] =
{
	0x2,	0x2,	0x1,	0x5,	0x5,	0x4,	0x8,	0x8,	0x7,
	0xB,	0xB,	0xA,	0xE,	0xE,	0xD,	0x11,	0x11,	0x10,
	0x14,	0x14,	0x13,	0x17,	0x17,	0x16,	0x1A,	0x1A,	0x19
};

int TblBoard_Block[81] =
{
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,
	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,
	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,
	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2
};

int TblBoard_BlockMask[81] =
{
	0x1,		0x2,		0x4,		0x8,		0x10,		0x20,		0x40,		0x80,		0x100,
	0x200,		0x400,		0x800,		0x1000,		0x2000,		0x4000,		0x8000,		0x10000,	0x20000,
	0x40000,	0x80000,	0x100000,	0x200000,	0x400000,	0x800000,	0x1000000,	0x2000000,	0x4000000,
	0x1,		0x2,		0x4,		0x8,		0x10,		0x20,		0x40,		0x80,		0x100,
	0x200,		0x400,		0x800,		0x1000,		0x2000,		0x4000,		0x8000,		0x10000,	0x20000,
	0x40000,	0x80000,	0x100000,	0x200000,	0x400000,	0x800000,	0x1000000,	0x2000000,	0x4000000,
	0x1,		0x2,		0x4,		0x8,		0x10,		0x20,		0x40,		0x80,		0x100,
	0x200,		0x400,		0x800,		0x1000,		0x2000,		0x4000,		0x8000,		0x10000,	0x20000,
	0x40000,	0x80000,	0x100000,	0x200000,	0x400000,	0x800000,	0x1000000,	0x2000000,	0x4000000
};

int TblSelfMask[81] =
{
	0x37E3F001,	0x37E3F002,	0x37E3F004,	0x371F8E08,	0x371F8E10,	0x371F8E20,	0x30FC7E40,	0x30FC7E80,	0x30FC7F00,
	0x2FE003F8,	0x2FE005F8,	0x2FE009F8,	0x2F1C11C7,	0x2F1C21C7,	0x2F1C41C7,	0x28FC803F,	0x28FD003F,	0x28FE003F,
	0x1807F1F8,	0x180BF1F8,	0x1813F1F8,	0x18238FC7,	0x18438FC7,	0x18838FC7,	0x19007E3F,	0x1A007E3F,	0x1C007E3F,
	0x37E3F001,	0x37E3F002,	0x37E3F004,	0x371F8E08,	0x371F8E10,	0x371F8E20,	0x30FC7E40,	0x30FC7E80,	0x30FC7F00,
	0x2FE003F8,	0x2FE005F8,	0x2FE009F8,	0x2F1C11C7,	0x2F1C21C7,	0x2F1C41C7,	0x28FC803F,	0x28FD003F,	0x28FE003F,
	0x1807F1F8,	0x180BF1F8,	0x1813F1F8,	0x18238FC7,	0x18438FC7,	0x18838FC7,	0x19007E3F,	0x1A007E3F,	0x1C007E3F,
	0x37E3F001,	0x37E3F002,	0x37E3F004,	0x371F8E08,	0x371F8E10,	0x371F8E20,	0x30FC7E40,	0x30FC7E80,	0x30FC7F00,
	0x2FE003F8,	0x2FE005F8,	0x2FE009F8,	0x2F1C11C7,	0x2F1C21C7,	0x2F1C41C7,	0x28FC803F,	0x28FD003F,	0x28FE003F,
	0x1807F1F8,	0x180BF1F8,	0x1813F1F8,	0x18238FC7,	0x18438FC7,	0x18838FC7,	0x19007E3F,	0x1A007E3F,	0x1C007E3F
};

int TblOtherMask[81] =
{
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF,
	0x3FFBFDFE,	0x3FF7FBFD,	0x3FEFF7FB,	0x3FDFEFF7,	0x3FBFDFEF,	0x3F7FBFDF,	0x3EFF7FBF,	0x3DFEFF7F,	0x3BFDFEFF
};

int TblMaskSingle[512] =
{
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FDFEFF7,	0x3FDBEDF6,	0x3FD7EBF5,	0x3FDFEFF7,	0x3FCFE7F3,	0x3FDFEFF7,	0x3FDFEFF7,	0x3FDFEFF7,
	0x3FBFDFEF,	0x3FBBDDEE,	0x3FB7DBED,	0x3FBFDFEF,	0x3FAFD7EB,	0x3FBFDFEF,	0x3FBFDFEF,	0x3FBFDFEF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3F7FBFDF,	0x3F7BBDDE,	0x3F77BBDD,	0x3F7FBFDF,	0x3F6FB7DB,	0x3F7FBFDF,	0x3F7FBFDF,	0x3F7FBFDF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3EFF7FBF,	0x3EFB7DBE,	0x3EF77BBD,	0x3EFF7FBF,	0x3EEF77BB,	0x3EFF7FBF,	0x3EFF7FBF,	0x3EFF7FBF,
	0x3EDF6FB7,	0x3EDB6DB6,	0x3ED76BB5,	0x3EDF6FB7,	0x3ECF67B3,	0x3EDF6FB7,	0x3EDF6FB7,	0x3EDF6FB7,
	0x3EBF5FAF,	0x3EBB5DAE,	0x3EB75BAD,	0x3EBF5FAF,	0x3EAF57AB,	0x3EBF5FAF,	0x3EBF5FAF,	0x3EBF5FAF,
	0x3EFF7FBF,	0x3EFB7DBE,	0x3EF77BBD,	0x3EFF7FBF,	0x3EEF77BB,	0x3EFF7FBF,	0x3EFF7FBF,	0x3EFF7FBF,
	0x3E7F3F9F,	0x3E7B3D9E,	0x3E773B9D,	0x3E7F3F9F,	0x3E6F379B,	0x3E7F3F9F,	0x3E7F3F9F,	0x3E7F3F9F,
	0x3EFF7FBF,	0x3EFB7DBE,	0x3EF77BBD,	0x3EFF7FBF,	0x3EEF77BB,	0x3EFF7FBF,	0x3EFF7FBF,	0x3EFF7FBF,
	0x3EFF7FBF,	0x3EFB7DBE,	0x3EF77BBD,	0x3EFF7FBF,	0x3EEF77BB,	0x3EFF7FBF,	0x3EFF7FBF,	0x3EFF7FBF,
	0x3EFF7FBF,	0x3EFB7DBE,	0x3EF77BBD,	0x3EFF7FBF,	0x3EEF77BB,	0x3EFF7FBF,	0x3EFF7FBF,	0x3EFF7FBF,
	0x3DFEFF7F,	0x3DFAFD7E,	0x3DF6FB7D,	0x3DFEFF7F,	0x3DEEF77B,	0x3DFEFF7F,	0x3DFEFF7F,	0x3DFEFF7F,
	0x3DDEEF77,	0x3DDAED76,	0x3DD6EB75,	0x3DDEEF77,	0x3DCEE773,	0x3DDEEF77,	0x3DDEEF77,	0x3DDEEF77,
	0x3DBEDF6F,	0x3DBADD6E,	0x3DB6DB6D,	0x3DBEDF6F,	0x3DAED76B,	0x3DBEDF6F,	0x3DBEDF6F,	0x3DBEDF6F,
	0x3DFEFF7F,	0x3DFAFD7E,	0x3DF6FB7D,	0x3DFEFF7F,	0x3DEEF77B,	0x3DFEFF7F,	0x3DFEFF7F,	0x3DFEFF7F,
	0x3D7EBF5F,	0x3D7ABD5E,	0x3D76BB5D,	0x3D7EBF5F,	0x3D6EB75B,	0x3D7EBF5F,	0x3D7EBF5F,	0x3D7EBF5F,
	0x3DFEFF7F,	0x3DFAFD7E,	0x3DF6FB7D,	0x3DFEFF7F,	0x3DEEF77B,	0x3DFEFF7F,	0x3DFEFF7F,	0x3DFEFF7F,
	0x3DFEFF7F,	0x3DFAFD7E,	0x3DF6FB7D,	0x3DFEFF7F,	0x3DEEF77B,	0x3DFEFF7F,	0x3DFEFF7F,	0x3DFEFF7F,
	0x3DFEFF7F,	0x3DFAFD7E,	0x3DF6FB7D,	0x3DFEFF7F,	0x3DEEF77B,	0x3DFEFF7F,	0x3DFEFF7F,	0x3DFEFF7F,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FDFEFF7,	0x3FDBEDF6,	0x3FD7EBF5,	0x3FDFEFF7,	0x3FCFE7F3,	0x3FDFEFF7,	0x3FDFEFF7,	0x3FDFEFF7,
	0x3FBFDFEF,	0x3FBBDDEE,	0x3FB7DBED,	0x3FBFDFEF,	0x3FAFD7EB,	0x3FBFDFEF,	0x3FBFDFEF,	0x3FBFDFEF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3F7FBFDF,	0x3F7BBDDE,	0x3F77BBDD,	0x3F7FBFDF,	0x3F6FB7DB,	0x3F7FBFDF,	0x3F7FBFDF,	0x3F7FBFDF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3BFDFEFF,	0x3BF9FCFE,	0x3BF5FAFD,	0x3BFDFEFF,	0x3BEDF6FB,	0x3BFDFEFF,	0x3BFDFEFF,	0x3BFDFEFF,
	0x3BDDEEF7,	0x3BD9ECF6,	0x3BD5EAF5,	0x3BDDEEF7,	0x3BCDE6F3,	0x3BDDEEF7,	0x3BDDEEF7,	0x3BDDEEF7,
	0x3BBDDEEF,	0x3BB9DCEE,	0x3BB5DAED,	0x3BBDDEEF,	0x3BADD6EB,	0x3BBDDEEF,	0x3BBDDEEF,	0x3BBDDEEF,
	0x3BFDFEFF,	0x3BF9FCFE,	0x3BF5FAFD,	0x3BFDFEFF,	0x3BEDF6FB,	0x3BFDFEFF,	0x3BFDFEFF,	0x3BFDFEFF,
	0x3B7DBEDF,	0x3B79BCDE,	0x3B75BADD,	0x3B7DBEDF,	0x3B6DB6DB,	0x3B7DBEDF,	0x3B7DBEDF,	0x3B7DBEDF,
	0x3BFDFEFF,	0x3BF9FCFE,	0x3BF5FAFD,	0x3BFDFEFF,	0x3BEDF6FB,	0x3BFDFEFF,	0x3BFDFEFF,	0x3BFDFEFF,
	0x3BFDFEFF,	0x3BF9FCFE,	0x3BF5FAFD,	0x3BFDFEFF,	0x3BEDF6FB,	0x3BFDFEFF,	0x3BFDFEFF,	0x3BFDFEFF,
	0x3BFDFEFF,	0x3BF9FCFE,	0x3BF5FAFD,	0x3BFDFEFF,	0x3BEDF6FB,	0x3BFDFEFF,	0x3BFDFEFF,	0x3BFDFEFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FDFEFF7,	0x3FDBEDF6,	0x3FD7EBF5,	0x3FDFEFF7,	0x3FCFE7F3,	0x3FDFEFF7,	0x3FDFEFF7,	0x3FDFEFF7,
	0x3FBFDFEF,	0x3FBBDDEE,	0x3FB7DBED,	0x3FBFDFEF,	0x3FAFD7EB,	0x3FBFDFEF,	0x3FBFDFEF,	0x3FBFDFEF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3F7FBFDF,	0x3F7BBDDE,	0x3F77BBDD,	0x3F7FBFDF,	0x3F6FB7DB,	0x3F7FBFDF,	0x3F7FBFDF,	0x3F7FBFDF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FDFEFF7,	0x3FDBEDF6,	0x3FD7EBF5,	0x3FDFEFF7,	0x3FCFE7F3,	0x3FDFEFF7,	0x3FDFEFF7,	0x3FDFEFF7,
	0x3FBFDFEF,	0x3FBBDDEE,	0x3FB7DBED,	0x3FBFDFEF,	0x3FAFD7EB,	0x3FBFDFEF,	0x3FBFDFEF,	0x3FBFDFEF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3F7FBFDF,	0x3F7BBDDE,	0x3F77BBDD,	0x3F7FBFDF,	0x3F6FB7DB,	0x3F7FBFDF,	0x3F7FBFDF,	0x3F7FBFDF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FDFEFF7,	0x3FDBEDF6,	0x3FD7EBF5,	0x3FDFEFF7,	0x3FCFE7F3,	0x3FDFEFF7,	0x3FDFEFF7,	0x3FDFEFF7,
	0x3FBFDFEF,	0x3FBBDDEE,	0x3FB7DBED,	0x3FBFDFEF,	0x3FAFD7EB,	0x3FBFDFEF,	0x3FBFDFEF,	0x3FBFDFEF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3F7FBFDF,	0x3F7BBDDE,	0x3F77BBDD,	0x3F7FBFDF,	0x3F6FB7DB,	0x3F7FBFDF,	0x3F7FBFDF,	0x3F7FBFDF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x3FFFFFFF,	0x3FFBFDFE,	0x3FF7FBFD,	0x3FFFFFFF,	0x3FEFF7FB,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF
};

int TblMaskDouble[512] =
{
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x4924924,	0x0,		0x48A4522,	0x4864321,	0x49E4F27,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x4522914,	0x0,		0x44A2512,	0x4462311,	0x45E2F17,
	0x0,		0x0,		0x0,		0x432190C,	0x0,		0x42A150A,	0x4261309,	0x43E1F0F,
	0x0,		0x0,		0x0,		0x4F2793C,	0x0,		0x4EA753A,	0x4E67339,	0x4FE7F3F,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x29148A4,	0x0,		0x28944A2,	0x28542A1,	0x29D4EA7,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x2512894,	0x0,		0x2492492,	0x2452291,	0x25D2E97,
	0x0,		0x0,		0x0,		0x231188C,	0x0,		0x229148A,	0x2251289,	0x23D1E8F,
	0x0,		0x0,		0x0,		0x2F178BC,	0x0,		0x2E974BA,	0x2E572B9,	0x2FD7EBF,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x190C864,	0x0,		0x188C462,	0x184C261,	0x19CCE67,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x150A854,	0x0,		0x148A452,	0x144A251,	0x15CAE57,
	0x0,		0x0,		0x0,		0x130984C,	0x0,		0x128944A,	0x1249249,	0x13C9E4F,
	0x0,		0x0,		0x0,		0x1F0F87C,	0x0,		0x1E8F47A,	0x1E4F279,	0x1FCFE7F,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x793C9E4,	0x0,		0x78BC5E2,	0x787C3E1,	0x79FCFE7,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x753A9D4,	0x0,		0x74BA5D2,	0x747A3D1,	0x75FAFD7,
	0x0,		0x0,		0x0,		0x73399CC,	0x0,		0x72B95CA,	0x72793C9,	0x73F9FCF,
	0x0,		0x0,		0x0,		0x7F3F9FC,	0x0,		0x7EBF5FA,	0x7E7F3F9,	0x7FFFFFF
};

int TblRowMask[8] =
{
	0x7FFFFFF,	0x7FFFE00,	0x7FC01FF,	0x7FC0000,	0x3FFFF,	0x3FE00,	0x1FF,		0x0
};

bool TblUniqFlag[8] =
{
	true,	true,	true,	false,	true,	false,	false,	false
};

byte TblShrinkMask[512] =
{
	0x0,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,	0x1,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x2,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,	0x3,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x4,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,	0x5,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,
	0x6,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7,	0x7
};

int TblRowUniq[512] =
{
	0x7,	0x6,	0x6,	0x6,	0x6,	0x6,	0x6,	0x6,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x5,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,	0x4,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x3,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,	0x2,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x1,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
};

int TblComplexMask[512] =
{
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x3FFFFFFF,	0x3F1C71C0,	0x381FF1C0,	0x3F1FF1C0,
	0x0,		0x0,		0x0,		0x0,		0x38FC71C0,	0x3FFC71C0,	0x3FFFF1C0,	0x3FFFF1C0,
	0x0,		0x0,		0x3FFFFFFF,	0x38FF8038,	0x0,		0x0,		0x381FF038,	0x38FFF038,
	0x0,		0x0,		0x3F1F8038,	0x3FFF8038,	0x0,		0x0,		0x3FFFF038,	0x3FFFF038,
	0x0,		0x0,		0x381F81F8,	0x3FFF81F8,	0x381C71F8,	0x3FFC71F8,	0x3FFFFFFF,	0x3FFFF1F8,
	0x0,		0x0,		0x3F1F81F8,	0x3FFF81F8,	0x38FC71F8,	0x3FFC71F8,	0x3FFFF1F8,	0x3FFFF1F8,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x3FFFFFFF,	0x38E38FC0,	0x3FE00FC0,	0x3FE38FC0,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x38FC0FC0,	0x3FFF8FC0,	0x3FFC0FC0,	0x3FFF8FC0,
	0x0,		0x3FFFFFFF,	0x0,		0x38FF8007,	0x0,		0x38E38E07,	0x0,		0x38FF8E07,
	0x0,		0x38E381C7,	0x0,		0x3FFF81C7,	0x38E00FC7,	0x3FFFFFFF,	0x3FFC0FC7,	0x3FFF8FC7,
	0x0,		0x3FE38007,	0x0,		0x3FFF8007,	0x0,		0x3FFF8E07,	0x0,		0x3FFF8E07,
	0x0,		0x3FE381C7,	0x0,		0x3FFF81C7,	0x38FC0FC7,	0x3FFF8FC7,	0x3FFC0FC7,	0x3FFF8FC7,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x0,		0x0,		0x38E07FC0,	0x38E3FFC0,	0x3FE3FFC0,	0x3FE3FFC0,
	0x0,		0x0,		0x0,		0x0,		0x381C7FC0,	0x3F1FFFC0,	0x381FFFC0,	0x3F1FFFC0,
	0x0,		0x0,		0x0,		0x0,		0x3FFFFFFF,	0x3FFFFFC0,	0x3FFFFFC0,	0x3FFFFFC0,
	0x0,		0x38E3803F,	0x381F803F,	0x3FFFFFFF,	0x0,		0x38E3FE3F,	0x381FFE3F,	0x38FFFE3F,
	0x0,		0x38E381FF,	0x3F1F81FF,	0x3FFF81FF,	0x38E07FFF,	0x38E3FFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x3FE381FF,	0x381F81FF,	0x3FFF81FF,	0x381C7FFF,	0x3FFFFFFF,	0x381FFFFF,	0x3FFFFFFF,
	0x0,		0x3FE381FF,	0x3F1F81FF,	0x3FFF81FF,	0x38FC7FFF,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x3FFFFFFF,	0x3F007E38,	0x0,		0x0,		0x3FE00E38,	0x3FE07E38,
	0x0,		0x3FFFFFFF,	0x0,		0x3F007E07,	0x0,		0x3F1C7007,	0x0,		0x3F1C7E07,
	0x0,		0x3F00703F,	0x3F000E3F,	0x3FFFFFFF,	0x0,		0x3FFC703F,	0x3FFC0E3F,	0x3FFC7E3F,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x3F1C0E38,	0x3FFC7E38,	0x0,		0x0,		0x3FFC0E38,	0x3FFC7E38,
	0x0,		0x3FE07007,	0x0,		0x3FFC7E07,	0x0,		0x3FFC7007,	0x0,		0x3FFC7E07,
	0x0,		0x3FE0703F,	0x3F1C0E3F,	0x3FFC7E3F,	0x0,		0x3FFC703F,	0x3FFC0E3F,	0x3FFC7E3F,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x3F038E38,	0x3F03FE38,	0x0,		0x0,		0x3FE3FE38,	0x3FE3FE38,
	0x0,		0x3F0071C7,	0x0,		0x3F03FFC7,	0x381C71C7,	0x3FFFFFFF,	0x381FFFC7,	0x3F1FFFC7,
	0x0,		0x3F0071FF,	0x3F038FFF,	0x3F03FFFF,	0x38FC71FF,	0x3FFC71FF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x0,		0x381F8E38,	0x38FFFE38,	0x0,		0x0,		0x381FFE38,	0x38FFFE38,
	0x0,		0x0,		0x3FFFFFFF,	0x3FFFFE38,	0x0,		0x0,		0x3FFFFE38,	0x3FFFFE38,
	0x0,		0x3FE071FF,	0x381F8FFF,	0x3FFFFFFF,	0x381C71FF,	0x3FFC71FF,	0x381FFFFF,	0x3FFFFFFF,
	0x0,		0x3FE071FF,	0x3F1F8FFF,	0x3FFFFFFF,	0x38FC71FF,	0x3FFC71FF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x3F000FF8,	0x3F03FFF8,	0x38E00FF8,	0x38E3FFF8,	0x3FFFFFFF,	0x3FE3FFF8,
	0x0,		0x3F03F007,	0x0,		0x3F03FE07,	0x0,		0x3F1FFE07,	0x0,		0x3F1FFE07,
	0x0,		0x3F03F1FF,	0x3F000FFF,	0x3F03FFFF,	0x38FC0FFF,	0x3FFFFFFF,	0x3FFC0FFF,	0x3FFFFFFF,
	0x0,		0x38E3F007,	0x0,		0x38FFFE07,	0x0,		0x38E3FE07,	0x0,		0x38FFFE07,
	0x0,		0x38E3F1FF,	0x3F1C0FFF,	0x3FFFFFFF,	0x38E00FFF,	0x38E3FFFF,	0x3FFC0FFF,	0x3FFFFFFF,
	0x0,		0x3FFFFFFF,	0x0,		0x3FFFFE07,	0x0,		0x3FFFFE07,	0x0,		0x3FFFFE07,
	0x0,		0x3FE3F1FF,	0x3F1C0FFF,	0x3FFFFFFF,	0x38FC0FFF,	0x3FFFFFFF,	0x3FFC0FFF,	0x3FFFFFFF,
	0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,		0x0,
	0x0,		0x0,		0x3F038FF8,	0x3F03FFF8,	0x38E07FF8,	0x38E3FFF8,	0x3FE3FFF8,	0x3FE3FFF8,
	0x0,		0x3F03F1C7,	0x0,		0x3F03FFC7,	0x381C7FC7,	0x3F1FFFC7,	0x381FFFC7,	0x3F1FFFC7,
	0x0,		0x3F03F1FF,	0x3F038FFF,	0x3F03FFFF,	0x38FC7FFF,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x38E3F03F,	0x381F8E3F,	0x38FFFE3F,	0x0,		0x38E3FE3F,	0x381FFE3F,	0x38FFFE3F,
	0x0,		0x38E3F1FF,	0x3F1F8FFF,	0x3FFFFFFF,	0x38E07FFF,	0x38E3FFFF,	0x3FFFFFFF,	0x3FFFFFFF,
	0x0,		0x3FE3F1FF,	0x381F8FFF,	0x3FFFFFFF,	0x381C7FFF,	0x3FFFFFFF,	0x381FFFFF,	0x3FFFFFFF,
	0x0,		0x3FE3F1FF,	0x3F1F8FFF,	0x3FFFFFFF,	0x38FC7FFF,	0x3FFFFFFF,	0x3FFFFFFF,	0x3FFFFFFF
};

int TblColumnSingle[512] =
{
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x1FF,	0x1FF,	0x1B6,	0x1FF,	0x1B6,	0x1B6,	0x1B6,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x16D,	0x16D,	0x124,	0x16D,	0x124,	0x124,	0x124,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0xDB,	0xDB,	0x92,	0xDB,	0x92,	0x92,	0x92,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0,
	0x0,	0x49,	0x49,	0x0,	0x49,	0x0,	0x0,	0x0
};

int TblShrinkSingle[512] =
{
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x54,	0x54,	0x54,	0x54,
	0x0,	0x0,	0x0,	0x0,	0x54,	0x54,	0x54,	0x54,
	0x0,	0x0,	0x62,	0x62,	0x0,	0x0,	0x62,	0x62,
	0x0,	0x0,	0x62,	0x62,	0x0,	0x0,	0x62,	0x62,
	0x0,	0x0,	0x62,	0x62,	0x54,	0x54,	0x40,	0x40,
	0x0,	0x0,	0x62,	0x62,	0x54,	0x54,	0x40,	0x40,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x8C,	0x8C,	0x8C,	0x8C,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x8C,	0x8C,	0x8C,	0x8C,
	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,
	0x0,	0xA1,	0x0,	0xA1,	0x8C,	0x80,	0x8C,	0x80,
	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,
	0x0,	0xA1,	0x0,	0xA1,	0x8C,	0x80,	0x8C,	0x80,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x8C,	0x8C,	0x8C,	0x8C,
	0x0,	0x0,	0x0,	0x0,	0x54,	0x54,	0x54,	0x54,
	0x0,	0x0,	0x0,	0x0,	0x4,	0x4,	0x4,	0x4,
	0x0,	0xA1,	0x62,	0x20,	0x0,	0xA1,	0x62,	0x20,
	0x0,	0xA1,	0x62,	0x20,	0x8C,	0x80,	0x0,	0x0,
	0x0,	0xA1,	0x62,	0x20,	0x54,	0x0,	0x40,	0x0,
	0x0,	0xA1,	0x62,	0x20,	0x4,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x10A,	0x10A,	0x0,	0x0,	0x10A,	0x10A,
	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,
	0x0,	0x111,	0x10A,	0x100,	0x0,	0x111,	0x10A,	0x100,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x10A,	0x10A,	0x0,	0x0,	0x10A,	0x10A,
	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,
	0x0,	0x111,	0x10A,	0x100,	0x0,	0x111,	0x10A,	0x100,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x10A,	0x10A,	0x0,	0x0,	0x10A,	0x10A,
	0x0,	0x111,	0x0,	0x111,	0x54,	0x10,	0x54,	0x10,
	0x0,	0x111,	0x10A,	0x100,	0x54,	0x10,	0x0,	0x0,
	0x0,	0x0,	0x62,	0x62,	0x0,	0x0,	0x62,	0x62,
	0x0,	0x0,	0x2,	0x2,	0x0,	0x0,	0x2,	0x2,
	0x0,	0x111,	0x62,	0x0,	0x54,	0x10,	0x40,	0x0,
	0x0,	0x111,	0x2,	0x0,	0x54,	0x10,	0x0,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x10A,	0x10A,	0x8C,	0x8C,	0x8,	0x8,
	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,	0x0,	0x111,
	0x0,	0x111,	0x10A,	0x100,	0x8C,	0x0,	0x8,	0x0,
	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,	0x0,	0xA1,
	0x0,	0xA1,	0x10A,	0x0,	0x8C,	0x80,	0x8,	0x0,
	0x0,	0x1,	0x0,	0x1,	0x0,	0x1,	0x0,	0x1,
	0x0,	0x1,	0x10A,	0x0,	0x8C,	0x0,	0x8,	0x0,
	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
	0x0,	0x0,	0x10A,	0x10A,	0x8C,	0x8C,	0x8,	0x8,
	0x0,	0x111,	0x0,	0x111,	0x54,	0x10,	0x54,	0x10,
	0x0,	0x111,	0x10A,	0x100,	0x4,	0x0,	0x0,	0x0,
	0x0,	0xA1,	0x62,	0x20,	0x0,	0xA1,	0x62,	0x20,
	0x0,	0xA1,	0x2,	0x0,	0x8C,	0x80,	0x0,	0x0,
	0x0,	0x1,	0x62,	0x0,	0x54,	0x0,	0x40,	0x0,
	0x0,	0x1,	0x2,	0x0,	0x4,	0x0,	0x0,	0x0
};

// End of code derived from tbl.c

int rj[27][11] =
{
	{	0,	1,	2,	3,	6,	9,	12,	15,	18,	21,	24	},
	{	1,	0,	2,	4,	7,	10,	13,	16,	19,	22,	25	},
	{	2,	0,	1,	5,	8,	11,	14,	17,	20,	23,	26	},
	{	3,	4,	5,	0,	6,	9,	12,	15,	18,	21,	24	},
	{	4,	3,	5,	1,	7,	10,	13,	16,	19,	22,	25	},
	{	5,	3,	4,	2,	8,	11,	14,	17,	20,	23,	26	},
	{	6,	7,	8,	0,	3,	9,	12,	15,	18,	21,	24	},
	{	7,	6,	8,	1,	4,	10,	13,	16,	19,	22,	25	},
	{	8,	6,	7,	2,	5,	11,	14,	17,	20,	23,	26	},
	{	9,	10,	11,	0,	3,	6,	12,	15,	18,	21,	24	},
	{	10,	9,	11,	1,	4,	7,	13,	16,	19,	22,	25	},
	{	11,	9,	10,	2,	5,	8,	14,	17,	20,	23,	26	},
	{	12,	13,	14,	0,	3,	6,	9,	15,	18,	21,	24	},
	{	13,	12,	14,	1,	4,	7,	10,	16,	19,	22,	25	},
	{	14,	12,	13,	2,	5,	8,	11,	17,	20,	23,	26	},
	{	15,	16,	17,	0,	3,	6,	9,	12,	18,	21,	24	},
	{	16,	15,	17,	1,	4,	7,	10,	13,	19,	22,	25	},
	{	17,	15,	16,	2,	5,	8,	11,	14,	20,	23,	26	},
	{	18,	19,	20,	0,	3,	6,	9,	12,	15,	21,	24	},
	{	19,	18,	20,	1,	4,	7,	10,	13,	16,	22,	25	},
	{	20,	18,	19,	2,	5,	8,	11,	14,	17,	23,	26	},
	{	21,	22,	23,	0,	3,	6,	9,	12,	15,	18,	24	},
	{	22,	21,	23,	1,	4,	7,	10,	13,	16,	19,	25	},
	{	23,	21,	22,	2,	5,	8,	11,	14,	17,	20,	26	},
	{	24,	25,	26,	0,	3,	6,	9,	12,	15,	18,	21	},
	{	25,	24,	26,	1,	4,	7,	10,	13,	16,	19,	22	},
	{	26,	24,	25,	2,	5,	8,	11,	14,	17,	20,	23	}
};

static byte		Board[81 + 1];		//Board
static CGame	G[60];				//Guess Board

static int		Index;				//Guess Index
static int		BlockMask[27];		//Block
static int		BlockMaskSum[3];	//Sum of BlockMask
static int		F[27];				//27-bit Full Mask
static int		CompF[27];			//Use for Compare

#if defined(_WIN32) || defined(_WINDOWS)
static unsigned long MilliTime(void)
{		// 1,000ths of a second of real time
	return(clock() / CLOCKS_PER_SEC * 1000);
}
#else
static unsigned long MilliTime(void)
{		// 1,000ths of a second of CPU time
	struct rusage usage;

	if (getrusage(RUSAGE_SELF, &usage)>=0) 
		return(usage.ru_utime.tv_sec*1000+usage.ru_utime.tv_usec/1000);
	return(0);
}
#endif // Windows

static void PrintComma(char *dest, unsigned long value)
{		// Format a number with commas
	if (value >= 1000000000)
		sprintf(dest, "%ld,%03ld,%03ld,%03ld", value / 1000000000, value / 1000000 % 1000, value / 1000 % 1000, value % 1000);
	else if (value >= 1000000)
		sprintf(dest, "%ld,%03ld,%03ld", value / 1000000, value / 1000 % 1000, value % 1000);
	else if (value >= 1000)
		sprintf(dest, "%ld,%03ld", value / 1000, value % 1000);
	else
		sprintf(dest, "%ld",value);
}

static const char *CommaStr(unsigned long value)
{		// Format a number with commas for (s,f)printf
	static int indx = 0;
	static char strs[4][16];

	indx = (indx + 1) & 3;
	PrintComma(strs[indx], value);
	return(strs[indx]);
}

static void InitSodoku()
{
	int i;		// JTL moved up
	int B;
	Index = 1;
	BlockMaskSum[0] = BlockMaskSum[1] = BlockMaskSum[2] = 0;
	for (i = 0; i < 27; i++)
	{
		CompF[i] = F[i] = BIT_SET_30;
		BlockMask[i] = 0;
	}
//Get Full Mask
	for (i = 80; i >= 0; i--)
	{
		if (Board[i] == '0')
			continue;
		B = TblMult3[Board[i] - '1'] + TblBoard_Block[i];
//Get BlockMask and Sum of BlockMask
		BlockMaskSum[TblBoard_Block[i]] |= TblBoard_BlockMask[i];
		BlockMask[B] |= TblBoard_BlockMask[i];
//Self and Another Block
		F[B] &= TblSelfMask[i];
		F[TblAnother1[B]] &= TblOtherMask[i];
		F[TblAnother2[B]] &= TblOtherMask[i];
	}
	BlockMaskSum[0] ^= BIT_SET_30;
	BlockMaskSum[1] ^= BIT_SET_30;
	BlockMaskSum[2] ^= BIT_SET_30;
	NORF(0) NORF(3) NORF(6) NORF(9) NORF(12)NORF(15)NORF(18)NORF(21)NORF(24)
	NORF(1) NORF(4) NORF(7) NORF(10)NORF(13)NORF(16)NORF(19)NORF(22)NORF(25)
	NORF(2) NORF(5) NORF(8) NORF(11)NORF(14)NORF(17)NORF(20)NORF(23)NORF(26)
}

static int SelectFirst(int mask)
{	// Select the first bit as the next guess
	return(mask & -mask);
}

// JTL - uniform interface

static bool Update()
{
	int Shrink = ~0, S, C1, C2, i;
	while (Shrink)
	{
		Shrink = 0;
		for(i = 0; i < 27; i++)
		{
			if (CompF[rj[i][0]] != F[rj[i][0]])
			{
				Shrink = FULL_TO_SHRINK(F[rj[i][0]]);
				if ((F[rj[i][0]] &= TblComplexMask[Shrink]) == 0)
					return false;
				S = FULL_TO_COLUMN(F[rj[i][0]]);
				C1 = S | FULL_TO_COLUMN(F[rj[i][1]]);
				C2 = S | FULL_TO_COLUMN(F[rj[i][2]]);
				F[rj[i][2]] &= TblMaskSingle[S] & TblMaskDouble[C1];
				F[rj[i][1]] &= TblMaskSingle[S] & TblMaskDouble[C2];
				S = TblRowUniq[TblShrinkSingle[Shrink] & TblColumnSingle[S]];
				if ((F[rj[i][0]] >> 27) != S)
				{
					F[rj[i][0]] &= S << 27 | BIT_SET_27;
					S = ~(F[rj[i][0]] & TblRowMask[S]);
					AN(F[rj[i][3]], S) AN(F[rj[i][4]], S) AN(F[rj[i][5]], S) AN(F[rj[i][6]], S)
					AN(F[rj[i][7]], S) AN(F[rj[i][8]], S) AN(F[rj[i][9]], S) AN(F[rj[i][10]], S)
				}
				CompF[rj[i][0]] = F[rj[i][0]];
			}
		}
	}
	return true;
}

static int T[3] = { 0x1FF, 0x3FE00, 0x7FC0000 };

static void Guess(int (*select)(int))
{
	int Line;
	int i;			// JTL moved up
	int Least = 10;	// JTL moved up
	int NumberOne;	// JTL moved up
	for (i = 0; i < 21; i++)
	{
		if (TblUniqFlag[F[i] >> 27])
			continue;
		G[Index].Block = i;
		if (TblNumberOne[HIGH_9_BIT(F[i])] == 2)
		{
			Line = 2;
			goto FoundLeast;
		}
		if (TblNumberOne[MID_9_BIT(F[i])] == 2)
		{
			Line = 1;
			goto FoundLeast;
		}
		if (TblNumberOne[LOW_9_BIT(F[i])] == 2)
		{
			Line = 0;
			goto FoundLeast;
		}
	}
	for (i = 0; i < 27; i++)
	{
		if (F[i] & 0x08000000)
		{
			NumberOne = TblNumberOne[LOW_9_BIT(F[i])];
			if (Least > NumberOne)
			{
				G[Index].Block = i;
				Line = 0;
				if ((Least = NumberOne) == 2)
					goto FoundLeast;
			}
		}
		if (F[i] & 0x10000000)
		{
			NumberOne = TblNumberOne[MID_9_BIT(F[i])];
			if (Least > NumberOne)
			{
				G[Index].Block = i;
				Line = 1;
				if ((Least = NumberOne) == 2)
					goto FoundLeast;
			}
		}
		if (F[i] & 0x20000000)
		{
			NumberOne = TblNumberOne[HIGH_9_BIT(F[i])];
			if (Least > NumberOne)
			{
				G[Index].Block = i;
				Line = 2;
				if ((Least = NumberOne) == 2)
					goto FoundLeast;
			}
		}
	}
FoundLeast:
	G[Index].Left = F[G[Index].Block] & T[Line];
	F[G[Index].Block] ^= G[Index].Left;
//Save Data
	SAVF(0) SAVF(1) SAVF(2) SAVF(3) SAVF(4) SAVF(5) SAVF(6) SAVF(7) SAVF(8)
	SAVF(9) SAVF(10)SAVF(11)SAVF(12)SAVF(13)SAVF(14)SAVF(15)SAVF(16)SAVF(17)
	SAVF(18)SAVF(19)SAVF(20)SAVF(21)SAVF(22)SAVF(23)SAVF(24)SAVF(25)SAVF(26)
	G[Index].Mask = (*select)(G[Index].Left);
	G[Index].Left ^= G[Index].Mask;
	F[G[Index].Block] ^= G[Index].Mask;
	Index++;
}

static bool Rollback(int (*select)(int))
{
	if (!--Index)
		return false;
//Restore Data
	RESF(0) RESF(1) RESF(2) RESF(3) RESF(4) RESF(5) RESF(6) RESF(7) RESF(8)
	RESF(9) RESF(10)RESF(11)RESF(12)RESF(13)RESF(14)RESF(15)RESF(16)RESF(17)
	RESF(18)RESF(19)RESF(20)RESF(21)RESF(22)RESF(23)RESF(24)RESF(25)RESF(26)
//Whether The Last Guess
	G[Index].Mask = (*select)(G[Index].Left);
	F[G[Index].Block] ^= G[Index].Mask;
	Index += (G[Index].Left ^= G[Index].Mask) != 0;
	return true;
}

int Calculate(int limit, char *solution, int (*select)(int))
{
	int numSolutions = 0;			// JTL - count number of solutions
	while (true)
	{
		if (Update())
		{
			if (   (F[18] | F[22] | F[26]) > BIT_SET_27
				|| (F[19] | F[23] | F[24]) > BIT_SET_27
				|| (F[20] | F[21] | F[25]) > BIT_SET_27
				|| (F[15] | F[16] | F[17]) > BIT_SET_27
				|| (F[12] | F[13] | F[14]) > BIT_SET_27
				|| (F[9]  | F[10] | F[11]) > BIT_SET_27
				|| (F[6]  | F[7]  | F[8] ) > BIT_SET_27
				|| (F[3]  | F[4]  | F[5] ) > BIT_SET_27)
			{
				Guess(select);
				continue;
			}
			++numSolutions;			// JTL - count number of solutions
			if (solution && numSolutions == 1)
			{
				int indx;
				for (indx = 0; indx < 81; indx++)
				{
					int mask = TblBoard_BlockMask[indx];
					int offset = TblBoard_Block[indx];
					int digit;
					for (digit = 0; digit < 9; ++digit)
					{
						if (F[offset] & mask)
						{
							solution[indx] = '1' + digit;
							break;
						}
						offset += 3;
					}
				}
				solution[81] = 0;
			}
			if (numSolutions >= limit)
				return(numSolutions);
		}
		if (!Rollback(select))	//Backtrack Over
			return(numSolutions);		// JTL - count number of solutions
	}
}

extern int ZhouSolveSelect(const char *puzzle, char *solution, int limit, int (*select)(int))
{	// Calculate the number of solutions
	int indx;
	for (indx = 0; indx < 81; ++indx)
	{
		if (isdigit(puzzle[indx]))
			Board[indx] = puzzle[indx];
		else if (puzzle[indx] == '.')
			Board[indx] = '0';
		else
			return(0);
	}
	InitSodoku();
	return(Calculate(limit, solution, select));
}

extern int ZhouSolver(const char *puzzle, char *solution, int limit)
{
	return(ZhouSolveSelect(puzzle, solution, limit, &SelectFirst));
}

int main(int argc, char *argv[])
{
	FILE *fd;
	unsigned long time, total = 0, temp;
	unsigned long counts[3] = {0,	0,	0};
	char buffer[1024], clues[82], *cptr, *dptr;
	if (argc > 1)
	{
		fd = fopen(argv[1], "r");
		if (!fd)
		{
			printf("Unable to open '%s' for input!\n", argv[1]);
			return(1);
		}
	}
	else
		fd = stdin;
	time = MilliTime();
	while (fgets(buffer, 1024, fd))
	{
		dptr = clues;
		for (cptr = buffer; *cptr && dptr - clues < 81; ++cptr)
		{
			if (isdigit(*cptr) || *cptr == '.')
				*dptr++ = *cptr;
			else if (*cptr == '#')
				break;
		}
		*dptr = 0;
		if (dptr - clues == 81)
		{
			++total;
			counts[ZhouSolver(clues, NULL, 2)] += 1;
		}
	}
	time = MilliTime() - time;
	fclose(fd);
	if (time == 0)
		time = 1;
	if (total < 42949)
		temp = (total * 100000) / time;
	else if (total < 429490)
		temp = (total * 10000) / ((time + 5) / 10);
	else if (total < 4294900)
		temp = (total * 1000) / ((time + 50) / 100);
	else if (total < 42949000)
		temp = (total * 100) / ((time + 500) / 1000);
	else if (total < 429490000)
		temp = (total * 10) / ((time + 5000) / 10000);
	else
		temp = total / ((time + 50000) / 100000);
	printf("Examined %s puzzles in %lu.%03lu seconds or %s.%02lu puzzles/sec\n",
		CommaStr(total), time / 1000, time % 1000, CommaStr(temp / 100), temp % 100);
	printf("Solved: %s puzzles, %s invalid, %s multi-solution\n",
		CommaStr(counts[1]), CommaStr(counts[0]), CommaStr(counts[2]));
	return(0);
}

/* END OF ZSolver.c - A very fast Sudoku solver */
