ftp.nice.ch/Attic/openStep/connectivity/mail/EnhanceMail.2.0b4.m.NIHS.bs.tgz#/EnhanceMail/XFace.m

This is XFace.m in view mode; [Download] [Up]

/* -*-C-*-
*******************************************************************************
*
* File:         XFace.m
* RCS:          $Header: /usr/local/lib/cvs/EnhanceMail/XFace.m,v 1.1.1.7 1996/04/17 01:26:11 cedman Exp $
* Description:  
* Author:       Carl Edman
* Created:      Tue Oct 17 08:06:48 1995
* Modified:     Mon Apr 15 22:17:29 1996 (Carl Edman) cedman@capitalist.princeton.edu
* Language:     C
* Package:      N/A
* Status:       Experimental (Do Not Distribute)
*
* (C) Copyright 1995, but otherwise this file is perfect freeware.
*
*******************************************************************************
*/

#import "XFace.h"
#import "MailApp.h"
#import <setjmp.h>

/*
 *  Compface - 48x48x1 image compression and decompression
 *
 *  Copyright (c) James Ashton - Sydney University - June 1990.
 *
 *  Written 11th November 1989.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#define EMBEDDED

/* need to know how many bits per hexadecimal digit for io */
#define BITSPERDIG 4
#ifndef EMBEDDED
static char HexDigits[]="0123456789ABCDEF";
#endif

/* define the face size - 48x48x1 */
#define WIDTH 48
#define HEIGHT WIDTH

/* total number of pixels and digits */
#define PIXELS (WIDTH * HEIGHT)
#define DIGITS (PIXELS / BITSPERDIG)

/* internal face representation - 1 char per pixel is faster */
static char F[PIXELS];

/* output formatting word lengths and line lengths */
#define DIGSPERWORD 4
#define WORDSPERLINE (WIDTH / DIGSPERWORD / BITSPERDIG)

/* compressed output uses the full range of printable characters.
 * in ascii these are in a contiguous block so we just need to know
 * the first and last.  The total number of printables is needed too */
#define FIRSTPRINT '!'
#define LASTPRINT '~'
#define NUMPRINTS (LASTPRINT - FIRSTPRINT + 1)

/* output line length for compressed data */
#define MAXLINELEN 70

/* Portable, very large unsigned integer arithmetic is needed.
 * Implementation uses arrays of WORDs.  COMPs must have at least
 * twice as many bits as WORDs to handle intermediate results */
#define WORD unsigned char
#define COMP unsigned long
#define BITSPERWORD 8
#define WORDCARRY (1 << BITSPERWORD)
#define WORDMASK (WORDCARRY - 1)
#define MAXWORDS ((PIXELS * 2 + BITSPERWORD - 1) / BITSPERWORD)

typedef struct bigint
   {
   int b_words;
   WORD b_word[MAXWORDS];
   } BigInt;

static BigInt B;

/* This is the guess the next pixel table.  Normally there are 12 neighbour
 * pixels used to give 1<<12 cases but in the upper left corner lesser
 * numbers of neighbours are available, leading to 6231 different guesses */
typedef struct guesses
   {
   char g_00[1<<12];
   char g_01[1<<7];
   char g_02[1<<2];
   char g_10[1<<9];
   char g_20[1<<6];
   char g_30[1<<8];
   char g_40[1<<10];
   char g_11[1<<5];
   char g_21[1<<3];
   char g_31[1<<5];
   char g_41[1<<6];
   char g_12[1<<1];
   char g_22[1<<0];
   char g_32[1<<2];
   char g_42[1<<2];
   } Guesses;

/* data.h was established by sampling over 1000 faces and icons */
static Guesses G =
   {
      {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
      0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0,
      0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1,
      1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
      0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,
      1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1,
      0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
      0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0,
      0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,
      1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
      0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
      1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
      0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
      1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1,
      1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
      0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
      1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
      0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
      0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1,
      0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
      0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
      1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
      0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0,
      1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1,
      1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0,
      1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0,
      1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0,
      1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
      1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	},
	{
      0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,
      0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1,
      0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
      1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1,
      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      },
      {
      0, 1, 0, 1, 
      },
      {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 
      1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
      0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
      0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 
      0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 
      0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
      0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 
      0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 
      1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 
      0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 
      1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 
      0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 
      0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 
      1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 
      0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 
      0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 
      },
      {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 
      1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 
      0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 
      1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 
      0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
      0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 
      0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 
      1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 
      0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 
      0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 
      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 
      0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 
      0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 
      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 
      0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 
      0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 0, 0, 1, 0, 1, 1, 1, 
      },
      {
      0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 
      0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 
      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 
      0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
      },
      {
      0, 1, 
      },
      {
      0, 
      },
      {
      0, 0, 0, 1, 
      },
      {
      0, 0, 0, 1, 
      }
   };

/* Data of varying probabilities are encoded by a value in the range 0 - 255.
 * The probability of the data determines the range of possible encodings.
 * Offset gives the first possible encoding of the range */
typedef struct prob
   {
   WORD p_range;
   WORD p_offset;
   } Prob;

/* A stack of probability values */
static Prob *ProbBuf[PIXELS * 2];
static int NumProbs=0;

/* Each face is encoded using 9 octrees of 16x16 each.  Each level of the
 * trees has varying probabilities of being white, grey or black.
 * The table below is based on sampling many faces */

#define BLACK 0
#define GREY 1
#define WHITE 2

static Prob levels[4][3] =
   {
      {{  1, 255}, {251,   0}, {   4, 251}}, /* Top of tree almost always grey */
      {{  1, 255}, {200,   0}, {  55, 200}},
      {{ 33, 223}, {159,   0}, {  64, 159}},
      {{131,   0}, {  0,   0}, { 125, 131}}  /* Grey disallowed at bottom */
   };

/* At the bottom of the octree 2x2 elements are considered black if any
 * pixel is black.  The probabilities below give the distribution of the
 * 16 possible 2x2 patterns.  All white is not really a possibility and
 * has a probability range of zero.  Again, experimentally derived data */
static Prob freqs[16] =
   {
      {0, 0}, {38, 0}, {38, 38}, {13, 152}, {38, 76}, {13, 165}, {13, 178},
      {6, 230}, {38, 114}, {13, 191}, {13, 204}, {6, 236}, {13, 217},
      {6, 242}, {5, 248}, {3, 253}
   };

/* successful completion */
#define ERR_OK          0
/* completed OK but some input was ignored */
#define ERR_EXCESS      1
/* insufficient input.  Bad face format? */
#define ERR_INSUFF     -1
/* Arithmetic overflow or buffer overflow */
#define ERR_INTERNAL   -2

#define GEN(g) F[h] ^= G.g[k]; break

static jmp_buf comp_env;
#ifndef EMBEDDED
static int status;
#endif

static int AllBlack(char *, int, int);
static int AllWhite(char *, int, int);
static int BigPop(Prob *);
static int Same(char *, int, int);

static void BigAdd(unsigned char);
static void BigClear(void);
static void BigDiv(unsigned char, unsigned char *);
static void BigMul(unsigned char);
static void BigPush(Prob *);
static void BigRead(const char *);
static void BigWrite(char *);
static void CompAll(char *);
static void Compress(char *, int, int, int);
static void Gen(char *);
static void GenFace(void);
static void PopGreys(char *, int, int);
static void PushGreys(char *, int, int);
static void RevPush(Prob *);
static void UnCompAll(const char *);
static void UnCompress(char *, int, int, int);
static void UnGenFace(void);
#ifndef EMBEDDED
static void BigPrint(void);
static void BigSub(unsigned char);
static void ReadFace(char *);
static void WriteFace(char *);
#endif

static void RevPush(Prob *p)
   {
   if (NumProbs >= PIXELS * 2 - 1)
      longjmp(comp_env, ERR_INTERNAL);
   ProbBuf[NumProbs++] = p;
   }
 
static void BigPush(Prob *p)
   {
   static WORD tmp;
   
   BigDiv(p->p_range, &tmp);
   BigMul(0);
   BigAdd(tmp + p->p_offset);
   }

static int BigPop(Prob *p)
   {
   static WORD tmp;
   int i;
   
   BigDiv(0, &tmp);
   i = 0;
   while ((tmp < p->p_offset) || (tmp >= p->p_range + p->p_offset))
      {
      p++;
      i++;
      }
   BigMul(p->p_range);
   BigAdd(tmp - p->p_offset);
   return i;
   }

#ifndef EMBEDDED
/* Print a BigInt in HexaDecimal */
static void BigPrint(void)
   {
   int i, c, count;
   WORD *w;

   count = 0;
   w = B.b_word + (i = B.b_words);
   while (i--)
      {
      w--;
      c = *((*w >> 4) + HexDigits);
      putc(c, stderr);
      c = *((*w & 0xf) + HexDigits);
      putc(c, stderr);
      if (++count >= 36)
         {
         putc('\\', stderr);
         putc('\n', stderr);
         count = 0;
         }
      }
   putc('\n', stderr);
   }
#endif

/* Divide B by a storing the result in B and the remainder in the word
 * pointer to by r */
static void BigDiv(WORD a, WORD *r)
   {
   int i;
   WORD *w;
   COMP c, d;

   a &= WORDMASK;
   if ((a == 1) || (B.b_words == 0))
      {
      *r = 0;
      return;
      }
   if (a == 0)	/* treat this as a == WORDCARRY */
      {			/* and just shift everything right a WORD */
      i = --B.b_words;
      w = B.b_word;
      *r = *w;
      while (i--)
         {
         *w = *(w + 1);
         w++;
         }
      *w = 0;
      return;
      }
   w = B.b_word + (i = B.b_words);
   c = 0;
   while (i--)
      {
      c <<= BITSPERWORD;
      c += (COMP)*--w;
      d = c / (COMP)a;
      c = c % (COMP)a;
      *w = (WORD)(d & WORDMASK);
      }
   *r = c;
   if (B.b_word[B.b_words - 1] == 0)
      B.b_words--;
   }

/* Multiply a by B storing the result in B */
static void BigMul(WORD a)
   {
   int i;
   WORD *w;
   COMP c;
   
   a &= WORDMASK;
   if ((a == 1) || (B.b_words == 0))
      return;
   if (a == 0)	/* treat this as a == WORDCARRY */
      {			/* and just shift everything left a WORD */
      if ((i = B.b_words++) >= MAXWORDS - 1)
         longjmp(comp_env, ERR_INTERNAL);
      w = B.b_word + i;
      while (i--)
         {
         *w = *(w - 1);
         w--;
         }
      *w = 0;
      return;
      }
   i = B.b_words;
   w = B.b_word;
   c = 0;
   while (i--)
      {
      c += (COMP)*w * (COMP)a;
      *(w++) = (WORD)(c & WORDMASK);
      c >>= BITSPERWORD;
      }
   if (c)
      {
      if (B.b_words++ >= MAXWORDS)
         longjmp(comp_env, ERR_INTERNAL);
      *w = (COMP)(c & WORDMASK);
      }
   }

#ifndef EMBEDDED
/* Subtract a from B storing the result in B */
static void BigSub(WORD a)
   {
   int i;
   WORD *w;
   COMP c;
   
   a &= WORDMASK;
   if (a == 0)
      return;
   i = 1;
   w = B.b_word;
   c = (COMP)*w - (COMP)a;
   *w = (WORD)(c & WORDMASK);
   while (c & WORDCARRY)
      {
      if (i >= B.b_words)
         longjmp(comp_env, ERR_INTERNAL);
      c = (COMP)*++w - 1;
      *w = (WORD)(c & WORDMASK);
      i++;
      }
   if ((i == B.b_words) && (*w == 0) && (i > 0))
      B.b_words--;
   }
#endif

/* Add to a to B storing the result in B */
static void BigAdd(WORD a)
   {
   int i;
   WORD *w;
   COMP c;
   
   a &= WORDMASK;
   if (a == 0)
      return;
   i = 0;
   w = B.b_word;
   c = a;
   while ((i < B.b_words) && c)
      {
      c += (COMP)*w;
      *w++ = (WORD)(c & WORDMASK);
      c >>= BITSPERWORD;
      i++;
      }
   if ((i == B.b_words) && c)
      {
      if (B.b_words++ >= MAXWORDS)
         longjmp(comp_env, ERR_INTERNAL);
      *w = (COMP)(c & WORDMASK);
      }
   }

static void BigClear(void)
   {
   B.b_words = 0;
   }

static int Same(char *f, int wid, int hei)
   {
   char val, *row;
   int x;
   
   val = *f;
   while (hei--)
      {
      row = f;
      x = wid;
      while (x--)
         if (*(row++) != val)
            return(0);
      f += WIDTH;
      }
   return 1;
   }

static int AllBlack(char *f, int wid, int hei)
   {
   if (wid > 3)
      {
      wid /= 2;
      hei /= 2;
      return (AllBlack(f, wid, hei) && AllBlack(f + wid, wid, hei) &&
              AllBlack(f + WIDTH * hei, wid, hei) &&
              AllBlack(f + WIDTH * hei + wid, wid, hei));
      }
   else
      return (*f || *(f + 1) || *(f + WIDTH) || *(f + WIDTH + 1));
   }

static int AllWhite(char *f, int wid, int hei)
   {
   return ((*f == 0) && Same(f, wid, hei));
   }

static void PopGreys(char *f, int wid, int hei)
   {
   if (wid > 3)
      {
      wid /= 2;
      hei /= 2;
      PopGreys(f, wid, hei);
      PopGreys(f + wid, wid, hei);
      PopGreys(f + WIDTH * hei, wid, hei);
      PopGreys(f + WIDTH * hei + wid, wid, hei);
      }
   else
      {
      wid = BigPop(freqs);
      if (wid & 1)
         *f = 1;
      if (wid & 2)
         *(f + 1) = 1;
      if (wid & 4)
         *(f + WIDTH) = 1;
      if (wid & 8)
         *(f + WIDTH + 1) = 1;
      }
   }

static void PushGreys(char *f, int wid, int hei)
   {
   if (wid > 3)
      {
      wid /= 2;
      hei /= 2;
      PushGreys(f, wid, hei);
      PushGreys(f + wid, wid, hei);
      PushGreys(f + WIDTH * hei, wid, hei);
      PushGreys(f + WIDTH * hei + wid, wid, hei);
      }
   else
      RevPush(freqs + *f + 2 * *(f + 1) + 4 * *(f + WIDTH) +
              8 * *(f + WIDTH + 1));
   }

static void UnCompress(char *f, int wid, int hei, int lev)
   {
   switch (BigPop(&levels[lev][0]))
      {
    case WHITE :
       return;
     case BLACK :
        PopGreys(f, wid, hei);
       return;
     default :
        wid /= 2;
       hei /= 2;
       lev++;
       UnCompress(f, wid, hei, lev);
       UnCompress(f + wid, wid, hei, lev);
       UnCompress(f + hei * WIDTH, wid, hei, lev);
       UnCompress(f + wid + hei * WIDTH, wid, hei, lev);
       return;
       }
   }

static void Compress(char *f, int wid, int hei, int lev)
   {
   if (AllWhite(f, wid, hei))
      {
      RevPush(&levels[lev][WHITE]);
      return;
      }
   if (AllBlack(f, wid, hei))
      {
      RevPush(&levels[lev][BLACK]);
      PushGreys(f, wid, hei);
      return;
      }
   RevPush(&levels[lev][GREY]);
   wid /= 2;
   hei /= 2;
   lev++;
   Compress(f, wid, hei, lev);
   Compress(f + wid, wid, hei, lev);
   Compress(f + hei * WIDTH, wid, hei, lev);
   Compress(f + wid + hei * WIDTH, wid, hei, lev);
   }

static void UnCompAll(const char *fbuf)
   {
   char *p;
   
   BigClear();
   BigRead(fbuf);
   p = F;
   while (p < F + PIXELS)
      *(p++) = 0;
   UnCompress(F, 16, 16, 0);
   UnCompress(F + 16, 16, 16, 0);
   UnCompress(F + 32, 16, 16, 0);
   UnCompress(F + WIDTH * 16, 16, 16, 0);
   UnCompress(F + WIDTH * 16 + 16, 16, 16, 0);
   UnCompress(F + WIDTH * 16 + 32, 16, 16, 0);
   UnCompress(F + WIDTH * 32, 16, 16, 0);
   UnCompress(F + WIDTH * 32 + 16, 16, 16, 0);
   UnCompress(F + WIDTH * 32 + 32, 16, 16, 0);
   }

static void CompAll(char *fbuf)
   {
   Compress(F, 16, 16, 0);
   Compress(F + 16, 16, 16, 0);
   Compress(F + 32, 16, 16, 0);
   Compress(F + WIDTH * 16, 16, 16, 0);
   Compress(F + WIDTH * 16 + 16, 16, 16, 0);
   Compress(F + WIDTH * 16 + 32, 16, 16, 0);
   Compress(F + WIDTH * 32, 16, 16, 0);
   Compress(F + WIDTH * 32 + 16, 16, 16, 0);
   Compress(F + WIDTH * 32 + 32, 16, 16, 0);
   BigClear();
   while (NumProbs > 0)
      BigPush(ProbBuf[--NumProbs]);
   BigWrite(fbuf);
   }

static void BigRead(const char *fbuf)
   {
   int c;
   
   while ((c=*fbuf++) != '\0')
      {
      if ((c < FIRSTPRINT) || (c > LASTPRINT)) continue;
      BigMul(NUMPRINTS);
      BigAdd((WORD)(c - FIRSTPRINT));
      }
   }

static void BigWrite(char *fbuf)
   {
   static WORD tmp;
   static char buf[DIGITS];
   char *s = buf;
   int pos;
   
   while (B.b_words > 0)
      {
      BigDiv(NUMPRINTS, &tmp);
      *(s++) = tmp + FIRSTPRINT;
      }

   pos=0;
   while (s-- > buf)
      {
      *fbuf++=*s;
      pos++;
      if (pos==MAXLINELEN)
         {
         *fbuf++='\n';
         *fbuf++=' ';
         pos=0;
         }
      }
   *fbuf++='\0';
   }

#ifndef EMBEDDED
static void ReadFace(char *fbuf)
   {
   int c, i;
   char *s, *t;
   
   t = s = fbuf;
   for(i = strlen(s); i > 0; i--)
      {
      c = (int)*(s++);
      if ((c >= '0') && (c <= '9'))
         {
         if (t >= fbuf + DIGITS)
            {
            status = ERR_EXCESS;
            break;
            }
         *(t++) = c - '0';
         }
      else if ((c >= 'A') && (c <= 'F'))
         {
         if (t >= fbuf + DIGITS)
            {
            status = ERR_EXCESS;
            break;
            }
         *(t++) = c - 'A' + 10;
         }
      else if ((c >= 'a') && (c <= 'f'))
         {
         if (t >= fbuf + DIGITS)
            {
            status = ERR_EXCESS;
            break;
            }
         *(t++) = c - 'a' + 10;
         }
      else if (((c == 'x') || (c == 'X')) && (t > fbuf) && (*(t-1) == 0))
         t--;
      }
   if (t < fbuf + DIGITS)
      longjmp(comp_env, ERR_INSUFF);
   s = fbuf;
   t = F;
   c = 1 << (BITSPERDIG - 1);
   while (t < F + PIXELS)
      {
      *(t++) = (*s & c) ? 1 : 0;
      if ((c >>= 1) == 0)
         {
         s++;
         c = 1 << (BITSPERDIG - 1);
         }
      }
   }

static void WriteFace(char *fbuf)
   {
   char *s, *t;
   int i, bits, digits, words;
   
   s = F;
   t = fbuf;
   bits = digits = words = i = 0;
   while (s < F + PIXELS)
      {
      if ((bits == 0) && (digits == 0))
         {
         *(t++) = '0';
         *(t++) = 'x';
         }
      if (*(s++))
         i = i * 2 + 1;
      else
         i *= 2;
      if (++bits == BITSPERDIG)
         {
         *(t++) = *(i + HexDigits);
         bits = i = 0;
         if (++digits == DIGSPERWORD)
            {
            *(t++) = ',';
            digits = 0;
            if (++words == WORDSPERLINE)
               {
               *(t++) = '\n';
               words = 0;
               }
            }
         }
      }
   *(t++) = '\0';
   }
#endif

static void Gen(char *f)
   {
   int m, l, k, j, i, h;
   
   for (j = 0; j < HEIGHT;  j++)
      {
      for (i = 0; i < WIDTH;  i++)
         {
         h = i + j * WIDTH;
         k = 0;
         for (l = i - 2; l <= i + 2; l++)
            for (m = j - 2; m <= j; m++)
               {
               if ((l >= i) && (m == j))
                  continue;
               if ((l > 0) && (l <= WIDTH) && (m > 0))
                  k = *(f + l + m * WIDTH) ? k * 2 + 1 : k * 2;
               }
         switch (i)
            {
          case 1 :
             switch (j)
                {
              case 1 : GEN(g_22);
              case 2 : GEN(g_21);
              default : GEN(g_20);
                }
             break;
           case 2 :
              switch (j)
                 {
               case 1 : GEN(g_12);
               case 2 : GEN(g_11);
               default : GEN(g_10);
                 }
             break;
           case WIDTH - 1 :
              switch (j)
                 {
               case 1 : GEN(g_42);
               case 2 : GEN(g_41);
               default : GEN(g_40);
                 }
             break;
           case WIDTH :
              switch (j)
                 {
               case 1 : GEN(g_32);
               case 2 : GEN(g_31);
               default : GEN(g_30);
                 }
             break;
           default :
              switch (j)
                 {
               case 1 : GEN(g_02);
               case 2 : GEN(g_01);
               default : GEN(g_00);
                 }
             break;
             }
         }
      }
   }

static void GenFace(void)
   {
   static char new[PIXELS];
   char *f1;
   char *f2;
   int i;
   
   f1 = new;
   f2 = F;
   i = PIXELS;
   while (i-- > 0)
      *(f1++) = *(f2++);
   Gen(new);
   }

static void UnGenFace(void)
   {
   Gen(F);
   }

@implementation NXImage(XFace)
- initXFace:(const char *)xface size:(const NXSize *)size
   {
   int x,y,avg;
   int basex,basey;
   unsigned char *data;
   NXBitmapImageRep *bitrep;

   [self initSize:size];

   switch (setjmp(comp_env))
      {
    case ERR_INSUFF:   /* insufficient input.  Bad face format? */
      [self logError:"Insufficient input decoding X face."];
      return nil;
    case ERR_INTERNAL: /* Arithmetic overflow or buffer overflow */
      [self logError:"Internal error in decoding X face."];
      return nil;
    case ERR_EXCESS:   /* completed OK but some input was ignored */
      [self logWarning:"Excessive data in X face string ignored."];
    case ERR_OK:       /* successful completion */
    default:
      break;
      }
   
   UnCompAll(xface);
   UnGenFace();

   bitrep=[[NXBitmapImageRep alloc] initData:0 pixelsWide:size->width pixelsHigh:size->height bitsPerSample:1 samplesPerPixel:1 hasAlpha:NO isPlanar:YES colorSpace:NX_OneIsBlackColorSpace bytesPerRow:0 bitsPerPixel:0];
   data=[bitrep data];

   basex=(size->width-WIDTH)/2;
   basey=(size->height-HEIGHT)/2;

   /* This double counts the corners, but that is ok, right ?
      In a heuristic anyway */
   avg=0;
   for(x=0;x<WIDTH;x++)  avg += F[0*WIDTH+x] + F[(HEIGHT-1)*WIDTH+x];
   for(y=0;y<HEIGHT;y++) avg += F[y*WIDTH+0] + F[y*WIDTH+(WIDTH-1)];
   avg=(avg > (WIDTH+HEIGHT));
   
   for(y=0;y<size->height;y++) for(x=0;x<size->width;x++)
      {
      int pos=x+y*size->width;
      
      if (((x>=basex) && (x<basex+WIDTH) && (y>=basey) && (y<basey+HEIGHT)) ?
          F[(y-basey)*WIDTH+(x-basex)] : avg)
         data[pos/8] |= 1<<(7-pos%8);
      else
         data[pos/8] &= ~(1<<(7-pos%8));
      }

   if (![self useRepresentation:bitrep])
      {
      bitrep=[bitrep free];
      return nil;
      }
   
   return self;
   }

- initXFace:(const char *)xface
   {
   NXSize s;
   s.width=WIDTH;
   s.height=HEIGHT;
   return [self initXFace:xface size:&s];
   }

- (char *)xFace
   {
   id list=[self representationList];
   int x,y;
   char *face;   
   NXBitmapImageRep *bitrep=nil;
   int bpp=0,width=0,height=0;
   unsigned char *data=0;
   NXColorSpace space=NX_CustomColorSpace;

   for(x=[list count]-1;x>=0;x--)
      {
      bitrep=[list objectAt:x];

      if (bitrep==nil) continue;
      if (![bitrep isKindOf:[NXBitmapImageRep class]]) continue;
      
      space=[bitrep colorSpace];
      bpp=[bitrep bitsPerPixel];
      data=[bitrep data];
      width=[bitrep pixelsWide];
      height=[bitrep pixelsHigh];
      
      if (((space==NX_OneIsBlackColorSpace)||(space==NX_OneIsWhiteColorSpace))
          && (width==WIDTH) && (height==HEIGHT))
         break;
      else
         bitrep=nil;
      }

   if (bitrep==nil)
      {
      [self logWarning:"No valid X face representation in image."];
      return 0;
      }
   
   for(y=0;y<HEIGHT;y++) for(x=0;x<WIDTH;x++)
      {
      int pos=(x+y*width)*bpp;

      F[x+y*WIDTH]=(data[pos/8]>>(7-pos%8))&1;
      if (space==NX_OneIsWhiteColorSpace)
         F[x+y*WIDTH]=!F[x+y*WIDTH];
      }

   switch (setjmp(comp_env))
      {
    case ERR_INSUFF:   /* insufficient input.  Bad face format? */
      [self logError:"Insufficient input encoding X face."];
      return 0;
    case ERR_INTERNAL: /* Arithmetic overflow or buffer overflow */
      [self logError:"Internal error in encoding X face."];
      return 0;
    case ERR_EXCESS:   /* completed OK but some input was ignored */
      [self logWarning:"Excessive data in X face string ignored."];
    case ERR_OK:       /* successful completion */
    default:
      break;
      }
   
   GenFace();
   face=malloc(DIGITS+DIGITS/MAXLINELEN*2+1);
   CompAll(face);
   return face;
   }

- initFromFile:(const char *)filename xFaceSize:(const NXSize *)s
   {
   id image;
   char *face;

   image=[[NXImage alloc] init];
   if (image==nil) return [self free];
   if ([image loadFromFile:filename]==NO) return [image free],[self free];
   face=[image xFace];
   image=[image free];
   if (face==0) return [self free];
   image=[self initXFace:face size:s];
   free(face);
   return image;
   }
@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.