commit d5f0f967f1ed43fcb4b4da6716bfd7f6e4bc00b8 Author: Colin Dean Date: Wed Oct 10 13:09:23 2012 -0400 import from http://ronja.twibright.com/optar/ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..248ec20 --- /dev/null +++ b/COPYING @@ -0,0 +1,353 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + on, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USAThis program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5c62e52 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +LDFLAGS=-lm +CFLAGS=-O3 -Wall -Wuninitialized -fomit-frame-pointer -funroll-loops \ + -fstrength-reduce -DNODEBUG `libpng-config --I_opts` + +all: optar unoptar + +install: + install optar /usr/local/bin/ + install unoptar /usr/local/bin + install pgm2ps /usr/local/bin + +uninstall: + rm /usr/local/bin/optar + rm /usr/local/bin/unoptar + rm /usr/local/bin/pgm2ps + +clean: + rm -f optar unoptar golay golay_codes.c *.o + +common.o: common.c optar.h + gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +parity.o: parity.c + gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +optar.o: optar.c optar.h font.h parity.h + gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +golay_codes.o: golay_codes.c + gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +golay.o: golay.c parity.h + gcc -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +unoptar.o: unoptar.c optar.h parity.h + gcc -c -I/usr/local/include/libpng $(CPPFLAGS) $(CFLAGS) -o $@ $< + +optar: optar.o common.o golay_codes.o parity.o + gcc $(LDFLAGS) -o $@ $^ + +golay_codes.c: golay + ./$< > $@ + +golay: golay.o parity.o + gcc $(LDFLAGS) -o $@ $^ + +unoptar: unoptar.o common.o golay_codes.o parity.o + gcc $(LDFLAGS) -o $@ -L/usr/local/lib -lpng -lz $^ diff --git a/README b/README new file mode 100644 index 0000000..a1ad5e3 --- /dev/null +++ b/README @@ -0,0 +1,113 @@ +Twibright Optar +--------------- + +This is a program to store data on paper using a 600dpi b/w laser printer and a +600+ dpi scanner. + +You need to install ImageMagick so that the resulting .pgm image can be converted into +PostScript with the right dimensions (so each pixel is 3x3 600dpi pixels so that +there is no unnecessary jitter). + +Make sure you have libpng installed and if you type "libpng-config" on the +commandline, there's a program which prints something. + +Compile with "make". Become root (su -) and type "make install". Now you have +optar, unoptar and pgm2ps installed on your system in /usr/local/bin. Later +you can uninstall by typing "make uninstall" the same way as you typed +"make install". + +Encoding (writing) +------------------ +Run + +./optar other_guys.ogg other_guys.ogg + +which will produce files: + +other_guys.ogg_0001.pgm +other_guys.ogg_0002.pgm +other_guys.ogg_0003.pgm +other_guys.ogg_0004.pgm +other_guys.ogg_0005.pgm +other_guys.ogg_0006.pgm + +Now convert them into PostScript using the included pgm2ps tool: +./pgm2ps *.pgm + +Print them using a 600dpi (or more) laser printer. Inkjet or dot matrix was +never tested and will not probably work at the pre-defined data density. See +"Changing the format" below. + +Please note that the file will be padded by zeroes and the original length will +be lost. Pack your data with tar if you store data that are sensitive to this. + +Decoding (reading) +------------------ + +Clean and polish the scanner glass with rubbing alcohol and paper towel. Put +yellow pages on the scanner lid to get sharper picture *). Insert the +page so that the text on the bottom is upright. Scan the pages into +PNG (not JPEG!) on 600dpi (or 1200dpi, slightly better): + +scan_0001.png +scan_0002.png +scan_0003.png +scan_0004.png +scan_0005.png +scan_0006.png + +Read the number sequence (format specification) from any of the papers and feed +it as 1st argument to the optar, 2nd argument is the filename part before the +underscore: + +unoptar 0-65-93-24-3-1-2-24 scan > out.ogg + +Then play out.ogg with mplayer. You should get first about 41 seconds from the +Ogg Vorbis file. + +*) In the scanner I tried (Canoscan), the lid didn't seem to be heavy enough to +press the paper down completely - there were blurry spots in the picture. +Without yellow pages I got 526 reparable bad bits bad from 3.2 million. With +yellow pages the blurry spots were much sharper and I got only 261 reparably +bad bits! + +Please note the data are padded with zeroes so the original information +about file length is lost. If your data format doesn't like this then first +pack your data with tar. + +A4 <-> US Letter +---------------- +Change the convert parameters in pgm2ps (see comments). Change XCROSSES +and YCROSSES in optar.h (see comments). Recompile. Then you can use US Letter +instead of A4. + +Changing the format +------------------- +If your printer is low quality and you are getting irreparable bits, you can +try to format the media to lower capacity. Unfortunately, setting by +commandline is not implemented yet. Change XCROSSES and YCROSSES in optar.h to +lower values which yields bigger pixels and lower capacity per page, but higher +reliability. Make sure they are in roughly the same proportion as before, +otherwise you get nonsquare pixels and unnecessary waste of channel capacity. + +You can also change the decoding parameters in unoptar.c (look for MAGIC +CONSTANTS) in attempt to read a difficult recording: unsharp_mask, +unsharp_dist, sync_white_cut, white_cut, minmax_filter, pixel_blur, cross_trim. + +Future improvement +================== +- manpage could be written for optar and unoptar +- commandline help (-h) could be written for optar and unoptar +- the format could be made configurable. Now it's stored in the optar.h +- the magic constants could be changed by commandline options. Now they are + stored in unoptar.c. +- Golay code decoding could be rewritten faster, using a sophisticated + algorithm (Kasami algorithm?) +- Easy support for multiple pages per page, so it can be read by a digital + camera. Currently it cannot since digital camera blurs at the sides of + the picture. + +(c) GPL 2007 Karel 'Clock' Kulhavy of Twibright Labs +See COPYING for the text of the GPL license. +e-mail: clock (at) twibright (dot) com +Twibright Optar homepage: http://ronja.twibright.com/optar/ diff --git a/common.c b/common.c new file mode 100644 index 0000000..8ffb282 --- /dev/null +++ b/common.c @@ -0,0 +1,69 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +#include /* fprintf */ + +#include "optar.h" + +/* Coordinates don't count with the border - 0,0 is upper left corner of the + * first cross! */ +int is_cross(unsigned x, unsigned y) +{ + x%=CPITCH; + y%=CPITCH; + return (x<2*CHALF&&y<2*CHALF); +} + +/* Returns the coords relative to the upperloeftmost cross upper left corner + * pixel! If you have borders, you have to add them! */ +void seq2xy(int *x, int *y, unsigned seq) +{ + unsigned rep; /* Repetition - number of narrow strip - wide strip pair, + starting with 0 */ + + if (seq>=TOTALBITS){ + /* Out of range */ + *x=-1; + *y=-1; + return; + } + /* We are sure we are in range. Document structure: + * - narrow strip (between top row of crosses), height is + * 2*CHALF + * - wide strip, height is CPITCH-2*CHALF + * - the above repeats (YCROSSES-1)-times + * - narrow strip + */ + rep=seq/REPPIXELS; + seq=seq%REPPIXELS; + + *y=REPHEIGHT*rep; + /* Now seq is sequence in the repetition pair */ + if (seq>=NARROWPIXELS){ + /* Second, wide strip of the pair */ + *y+=NARROWHEIGHT; + seq-=NARROWPIXELS; + /* Now seq is sequence in the wide strip */ + *y+=seq/WIDEWIDTH; + *x=seq%WIDEWIDTH; + }else{ + /* First, narrow strip of the pair */ + unsigned gap; /* Horizontal gap number */ + *x=2*CHALF; + *y+=seq/NARROWWIDTH; + seq%=NARROWWIDTH; + /* seq is now sequence in the horiz. line */ + gap=seq/GAPWIDTH; + *x+=gap*CPITCH; + seq%=GAPWIDTH; + /* seq is now sequence in the gap */ + *x+=seq; + } +} + +/* Golay codes */ +unsigned long golay(unsigned long in) +{ + return golay_codes[in&4095]; +} + + diff --git a/font.h b/font.h new file mode 100644 index 0000000..49e0b7a --- /dev/null +++ b/font.h @@ -0,0 +1,2529 @@ +/* GIMP header image file format (INDEXED): /var/www/htdocs/ronja/trunk/grx/optar/font.h */ + +static unsigned int width = 1500; +static unsigned int height = 24; + +/* Call this macro repeatedly. After each use, the pixel data can be extracted */ + +#define HEADER_PIXEL(data,pixel) {\ + pixel[0] = header_data_cmap[(unsigned char)data[0]][0]; \ + pixel[1] = header_data_cmap[(unsigned char)data[0]][1]; \ + pixel[2] = header_data_cmap[(unsigned char)data[0]][2]; \ + data ++; } + +static char header_data_cmap[256][3] = { + { 0, 0, 0}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255}, + {255,255,255} + }; +static char header_data[] = { + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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, + 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,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0, + 0,1,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,0,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1,1,0,0,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,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,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, + 1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1, + 1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1, + 1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,0,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,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,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,1,0,0,0,0,0,1,1,1,1,1, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,1, + 1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1, + 1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0, + 0,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1, + 1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, + 1,1,0,0,0,0,0,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,0,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,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,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,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,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,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,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, + 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,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,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0, + 0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 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,1,1,1,1,1,1,0,0,0,0,0,0, + 0,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,1,1,1,1,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,0,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,1,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0, + 1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1,1,1,0,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,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,0,0,0,0,0,0,0,0,1,1,0,0, + 0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1, + 1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1, + 1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1, + 1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1, + 1,1,0,0,0,0,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,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,0,0,0,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1, + 1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1, + 1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,1, + 1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0, + 1,1,1,1,0,0,1,1,1,0,0,0,0,0,1,1, + 1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, + 1,1,0,0,0,0,0,0,0,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,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,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,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,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,1,1,1,0,0,0,0,0,0,0,0,0,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,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,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,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, + 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,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 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,1,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,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,1,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,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,1,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0, + 1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,1,1,0,0,1,1,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,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,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,1, + 1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0, + 0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1, + 1,1,1,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0, + 0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,1, + 1,1,1,0,0,0,1,1,1,1,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,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,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,0,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0, + 0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1, + 1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0, + 0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0, + 1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,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,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,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,0,0,0,0,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,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,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,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,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,0,0,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, + 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,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,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1, + 1,0,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,0,0,0,0,1, + 1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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,1,1,1,1,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,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1, + 1,1,1,0,0,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,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0, + 1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0, + 0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,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,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, + 0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,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,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,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,1,1,0,0,0,0,0, + 0,1,1,0,1,1,0,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,1,0,0, + 0,0,1,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0, + 1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,1,1,1,1,0,1, + 1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,1,1,1,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,1, + 1,1,0,0,0,0,0,0,0,1,1,1,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,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,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,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,0,0,0,0,0,0,0,0,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,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,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,0,0,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, + 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,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,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,1,1,1,1,0,0,0,0,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,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,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,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,1,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,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, + 1,1,1,1,0,0,1,1,1,0,1,0,0,1,0,0, + 0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0, + 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,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,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,1,1,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,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,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,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,1,1,1,1,0,0, + 0,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0, + 1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,1,1,1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0, + 1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0, + 1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1, + 1,1,0,0,0,0,0,1,1,1,1,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1,1,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,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0, + 1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1, + 1,1,0,0,0,0,0,1,1,1,1,0,1,1,1,0, + 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1, + 1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1, + 1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1, + 0,1,1,1,1,0,0,0,1,1,1,0,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,0,1,1,1,0,0,0,0,0,1,1,1, + 0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0, + 1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1, + 1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0, + 0,0,0,0,0,1,1,1,1,0,0,0,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,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,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,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,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,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, + 1,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0, + 0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0, + 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,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,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0, + 0,1,1,0,0,0,1,1,1,0,1,1,0,0,0,0, + 1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,1,1,1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0, + 1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0, + 1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0, + 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0, + 0,0,0,1,1,1,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,1, + 1,1,0,0,0,0,0,1,1,1,0,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,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1, + 1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1, + 1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1, + 1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1, + 1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1, + 1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1, + 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,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,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,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0, + 0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 1,1,1,1,0,1,1,1,1,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,0,0,0,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,0,0,1, + 1,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,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,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0, + 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,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,0,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,1,1,0,0,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1, + 1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1, + 1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0, + 1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,0, + 0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0, + 1,0,1,1,1,0,0,1,1,1,0,1,1,0,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0, + 1,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,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,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,1,1,1,0,0,0,1,1,1,1, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,0,0,0,0,1,1,1,0,0,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1, + 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,1,0,0,1,1,1,0,0,0,0,1, + 1,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0, + 1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,1, + 1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,1,1,1,1,0,0,1,1,1,0,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,0,0,0,1,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1, + 1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0, + 0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 1,1,1,1,0,1,1,1,1,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,0,0,0,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,0,0,1, + 1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,1,1,1,1,0,0,0,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,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0, + 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,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,0,0,0,0, + 0,1,1,1,0,1,1,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1, + 1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1, + 1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 1,1,0,0,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,1,1,1,0,0,0,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1, + 1,0,1,1,1,0,0,1,1,1,0,1,1,0,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0, + 1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0, + 0,0,0,1,1,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,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,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0, + 1,1,1,0,0,1,1,0,0,0,0,1,1,1,0,1, + 1,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,1, + 1,1,1,0,1,1,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,0, + 0,0,0,0,0,1,1,1,1,0,0,1,1,1,0,0, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0, + 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1, + 1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,1, + 1,1,1,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,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,0,0,0,1, + 1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1, + 1,1,0,1,1,1,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,0,0,0,0,0,0,1,1,0,0,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,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,1,0,0,0,0,0, + 0,1,1,1,0,1,1,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,0,1,0,0,0,0,1,1,1,0,0,0,0,1, + 1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,1, + 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,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,1,1,1, + 1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,0,0,1,1,1,1,1,1,1, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1, + 1,0,1,1,1,0,0,1,1,1,0,0,1,1,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0, + 1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0, + 0,0,0,1,1,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,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,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0, + 1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,1,1,1,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1, + 1,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0, + 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,0, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,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,1,1,1,1,0,0,0,0,0,0,1, + 1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,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,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,0,0,1,1, + 1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,0,0,0,0,0,0,1,1,0,0,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,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,1,1,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,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,0, + 1,1,1,0,0,1,1,0,0,0,0,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1, + 1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,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,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, + 1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1, + 1,0,1,1,1,0,0,1,1,1,0,0,1,1,0,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1, + 1,0,1,1,0,1,1,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,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,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,1,1,1,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,0,0,1,1,1,0,0,0,0,1,1,0,0, + 1,1,1,0,0,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1, + 1,1,0,0,0,1,0,0,1,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,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,0, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,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,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1, + 1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,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, + 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1, + 1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1, + 0,0,1,0,0,0,0,0,1,1,1,1,1,0,1,1, + 1,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,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,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, + 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,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,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,0,0, + 1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1, + 1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1, + 1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,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,1,1,1,1, + 1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,1,1,1,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1, + 1,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1, + 1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,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,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,0,0,0,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1, + 1,0,1,0,1,1,1,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0, + 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,0,0,0,1,0,0,0,0,0,1,1,1, + 1,0,0,0,0,0,0,0,1,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,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1, + 1,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,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1, + 1,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,1,1,1,1,0,0, + 0,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,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0, + 0,0,1,1,1,1,0,0,0,0,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,0,0,0,1, + 1,1,1,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,0,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,1,1,1, + 0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1, + 1,0,0,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,1,1,1,0, + 0,0,0,0,0,0,0,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,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,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,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,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,0,0,0, + 1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1, + 1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1, + 1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,0,0,1,1,1,0,0,1,1,1,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1, + 0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1, + 1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,0,1,1,1, + 1,0,0,1,1,1,1,0,0,0,0,1,1,1,0,1, + 1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,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,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,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,1, + 1,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,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,0,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,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,1,1,0,1,1,1,0,0,0,0,0,0,1,1,1, + 1,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,0,0,0,0,1,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,1,1,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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, + 1,1,1,1,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,0,0,0,1,1,1,1,0,0,0,0,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,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,0,0,0,0,0,0,1,1,0,0,0,1,1, + 0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1, + 0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,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,0,1,1,1,0,0,0,0,0,0,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,0,0,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1, + 1,1,1,1,1,0,0,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, + 1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0, + 0,0,1,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0, + 1,1,1,0,0,0,1,1,1,1,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0, + 0,0,1,1,0,1,1,0,0,0,0,0,0,1,1,1, + 1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,0,0,0,0,0,0,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,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,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0, + 0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1, + 1,0,0,0,0,1,1,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, + 1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1, + 1,0,1,1,1,1,0,0,0,0,0,1,1,1,0,1, + 1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,0,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,1,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 1,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,0,0,0,0,1,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,1,1,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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, + 1,1,1,1,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,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,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,0,0,0,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,1,1,0,0,1,1,1, + 0,0,0,0,0,0,1,1,0,0,1,0,1,1,1,1, + 0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,1, + 1,1,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,1,1,0, + 0,0,0,0,0,0,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,0,0,1,1,1,0,0,0,0,0,0,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,0,0,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1, + 1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0, + 1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1, + 1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,1, + 1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 1,1,1,0,0,0,1,1,1,1,1,1,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,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,0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1, + 1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1, + 1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,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,0,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,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,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,0,0,1,1,1,1,0,0,0,1,1,1,1, + 0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0, + 0,1,0,0,0,0,1,1,1,0,0,1,1,1,1,0, + 0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1, + 0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0, + 0,0,1,1,1,1,0,0,1,1,1,0,0,0,0,1, + 1,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,0,0,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 1,0,1,1,1,1,0,0,0,0,1,1,1,1,0,1, + 1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0, + 0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1, + 1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1, + 1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1, + 1,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,1,1,1,1,0,0, + 0,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,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0, + 0,0,1,1,1,1,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,1,1,1,1,0,0,0,1, + 1,1,1,0,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,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,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,1,1,1, + 0,0,0,0,0,0,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,0,0,1,1,1,0,0,0,0,0,0,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,0,0,1,1,1,0,0, + 0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1, + 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1, + 1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,0,0,0,1,1,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,0,0,0,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1, + 1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1, + 1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1, + 1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,1,1,1,1,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,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, + 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,0,0,0,0,0,0,0,0,1, + 1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1, + 1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1, + 1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1, + 1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0, + 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,0,0,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,1,1,1,1,0,0,0,0,0,1, + 1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0, + 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,0,1,1,1,1,0,0, + 0,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,1,1,1,1,1,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,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,1,1,1,1,0,0,0,1, + 1,1,1,0,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,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0, + 0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,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,0,0,1,1,1,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1, + 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0, + 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,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,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1, + 1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1, + 1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0, + 1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,1,1,1,0,0,0,1,1, + 1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0, + 0,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1, + 1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,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,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,1,0,1,1,1,0,0,0,1,1,1,0, + 1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1, + 1,1,0,0,0,0,0,1,1,1,1,0,1,1,1,0, + 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0, + 0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1, + 1,1,0,1,1,1,0,0,0,0,1,1,1,0,0,0, + 1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0, + 0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,1,1,0,0,1,1, + 1,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1, + 1,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,0,1,1,1,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0, + 0,0,0,0,1,1,1,1,0,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0, + 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0, + 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0, + 0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1, + 1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0, + 0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0, + 0,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,1,1,1,1,1,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,0,0,0,1,1,1,1,0,0,0,1,1,1,1, + 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1, + 1,1,1,0,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,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,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,0,0,0,0,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,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,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,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,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,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,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,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,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, + 0,0,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,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,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,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, + 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,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,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,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,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,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,1,1,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0, + 0,0,0,0,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, + 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,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,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,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,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,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,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,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, + 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,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,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,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,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,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,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,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,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0, + 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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,0,0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,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,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,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,0, + 0,0,0,0,0,0,0,0,0,0,0,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,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, + 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,0,0,0,0,0,0,0,0,0,0,0, + 0,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,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,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,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,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,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, + 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,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,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,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,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,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,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,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,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, + 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,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, + 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,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,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,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,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,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,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, + 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,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,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,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,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,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,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, + 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,1,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,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,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,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,0, + 0,0,0,0,0,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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,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,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,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,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,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,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,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,1,1,1,1,1,1,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,0,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, + 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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0, + 0,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,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,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,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,1,0,0,0,0,0,0, + 0,1,1,1,0,0,0,0,0,0,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,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,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,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,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, + 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,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,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,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,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,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,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,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,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0 + }; diff --git a/golay.c b/golay.c new file mode 100644 index 0000000..382e36a --- /dev/null +++ b/golay.c @@ -0,0 +1,64 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +#include +#include + +#include "parity.h" + +int dodecahedron[12][5]={ + /* For each dodecahedron face (number in the comment, 1-12) there + * is a list of the 5 adjacent faces (1-12). See golay.svg for + * a drawing. */ + {/* 1 */ 2, 3, 4, 5, 6}, + {/* 2 */ 1, 3, 6, 7, 8}, + {/* 3 */ 1, 2, 4, 8, 9}, + {/* 4 */ 1, 3, 5, 9, 10}, + {/* 5 */ 1, 4, 6, 10, 11}, + {/* 6 */ 1, 2, 5, 7, 11}, + {/* 7 */ 2, 6, 8, 11, 12}, + {/* 8 */ 2, 3, 7, 9, 12}, + {/* 9 */ 3, 4, 8, 10, 12}, + {/* 10 */ 4, 5, 9, 11, 12}, + {/* 11 */ 5, 6, 7, 10, 12}, + {/* 12 */ 7, 8, 9, 10, 11} +}; + +unsigned parities[12]; + +int main(int argc, char ** argv) +{ + unsigned mask, p, f; + unsigned input; + unsigned prty; /* parity */ + + for (p=0;p<12;p++){ + mask=0xfff; /* All dodecahedron faces */ + for (f=0;f<5;f++) + mask^=1U<<(dodecahedron[p][f]-1); + parities[p]=mask; + } + + printf("unsigned long golay_codes[4096]={\n"); + + for (input=0;input<4096;input++){ + unsigned n_ones; + unsigned long codeword; + + prty=0; + for (p=0;p<12;p++){ + prty<<=1; + prty|=parity(input&parities[p]); + } + codeword=((unsigned long)input<<12)|prty; + n_ones=ones(codeword); + printf((input==4095?"0x%06lx\n":"0x%06lx,\n"),codeword); + assert(n_ones==0 + ||n_ones==8 + ||n_ones==12 + ||n_ones==16 + ||n_ones==24); + } + + printf("};\n"); + return 0; +} diff --git a/golay.svg b/golay.svg new file mode 100644 index 0000000..87a70d1 --- /dev/null +++ b/golay.svg @@ -0,0 +1,1298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + + 6 + + + 7 + + + 8 + + + 9 + + + 10 + + + 11 + + + 12 + + + + Twibright Labs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dodecahedron for the Golay code + + diff --git a/optar.c b/optar.c new file mode 100644 index 0000000..b7739ad --- /dev/null +++ b/optar.c @@ -0,0 +1,323 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +#include /* getchar */ +#include /* exit */ +#include /* memcpy */ +#include /* assert */ + +#define width font_width +#define height font_height +#include "font.h" +#undef width +#undef height + +#include "optar.h" +#include "parity.h" +#define HEIGHT (2*BORDER+DATA_HEIGHT+TEXT_HEIGHT) +#define TEXT_HEIGHT 24 + +static unsigned char ary[WIDTH*HEIGHT]; +static unsigned char *file_label=(unsigned char *)""; /* The filename written in the + file_label */ +static char *output_filename; /* The output filename */ +static unsigned output_filename_buffer_size; +static unsigned char *base=(unsigned char *)"optar_out"; /* Output filename base */ +static unsigned file_number; +FILE *output_stream; +FILE *input_stream; +unsigned n_pages; /* Number of pages calculated from the file length */ + +void dump_ary(void) +{ + fprintf(output_stream, + "P5\n" + "%u %u\n" + "255\n" + ,WIDTH, HEIGHT); + + fwrite(ary, sizeof(ary), 1, output_stream); +} + +/* Only the LSB is significant. Writes hamming-encoded bits. The sequence number + * must not be out of range! */ +void write_channelbit(unsigned char bit, unsigned long seq) +{ + int x,y; /* Positions of the pixel */ + + bit&=1; + bit=-bit; + bit=~bit; /* White=bit 0, black=bit 1 */ + seq2xy(&x, &y, seq); /* Returns without borders! */ + x+=BORDER; + y+=BORDER; + ary[x+y*WIDTH]=bit; + seq++; +} + +/* Groups into two groups of bits, 0...bit-1 and bit..., and then makes + * a gap with zero between them by shifting the higer bits up. */ +unsigned long split(unsigned long in, unsigned bit) +{ + unsigned long high; + + high=in; + in&=(1UL<=3 + in=split(in,4); +#if FEC_ORDER>=4 + in=split(in,8); +#if FEC_ORDER>=5 + in=split(in,16); + in|=parity(in&0xffff0000)<<16; +#endif + in|=parity(in&0xff00ff00)<<8; +#endif + in|=parity(in&0xf0f0f0f0)<<4; +#endif + in|=parity(in&0xcccccccc)<<2; + in|=parity(in&0xaaaaaaaa)<<1; + in|=parity(in); + return in; +} + +void border(void) +{ + unsigned c; + char *ptr=(char *)(void *)ary; + + memset(ptr,0,BORDER*WIDTH); + ptr+=BORDER*WIDTH; + for (c=DATA_HEIGHT;c;c--){ + memset(ptr,0,BORDER); + ptr+=WIDTH; + memset(ptr-BORDER,0,BORDER); + } + memset(ptr,0,TEXT_HEIGHT*WIDTH); + ptr+=TEXT_HEIGHT*WIDTH; + /* BORDER bytes into the bottom border */ + memset(ptr,0,BORDER*WIDTH); +} + +void cross(x,y) +{ + unsigned char *ptr=ary+y*WIDTH+x; + unsigned c; + + for (c=CHALF;c;c--,ptr+=WIDTH){ + memset(ptr,0,CHALF); + memset(ptr+CHALF,0xff,CHALF); + memset(ptr+CHALF*WIDTH,0xff,CHALF); + memset(ptr+CHALF*(WIDTH+1),0,CHALF); + } +} + +void crosses(void) +{ + unsigned x,y; + + for (y=BORDER;y<=HEIGHT-TEXT_HEIGHT-BORDER-2*CHALF;y+=CPITCH) + for (x=BORDER;x<=WIDTH-BORDER-2*CHALF;x+=CPITCH) + cross(x,y); +} + +/* x is in the range 0 to DATA_WIDTH-1 */ +void text_block (destx, srcx, width) +{ + int x, y; + unsigned char *srcptr; + unsigned char *destptr; + + if (destx+width>DATA_WIDTH) return; /* Letter doesn't fit */ + + srcptr=(unsigned char *)(void *)header_data+srcx; + destptr=ary+WIDTH*(BORDER+DATA_HEIGHT)+BORDER+destx; + + for (y=0;y=' '&&*ptr<=127){ + text_block(x,TEXT_WIDTH*(*ptr-' '), TEXT_WIDTH); + x+=TEXT_WIDTH; + } + } + +} + +void format_ary(void) +{ + memset(ary, 0xff, sizeof(ary)); /* White */ + border(); + crosses(); + label(); + +} + +/* Always formats ary. Dumps it if it's not the first one. */ +void new_file(void) +{ + if (file_number){ + dump_ary(); + fclose(output_stream); + } + if (file_number>=9999){ + fprintf(stderr,"optar: too many pages - 10,000 or more\n"); + exit(1); + } + snprintf(output_filename,output_filename_buffer_size + ,"%s_%04u.pgm",(char *)(void *)base,++file_number); + output_stream=fopen(output_filename,"w"); + if (!output_stream){ + fprintf(stderr,"optar: cannot open %s for writing.\n", output_filename); + exit(1); + } + format_ary(); +} + +/* That's the net channel capacity */ +void write_payloadbit(unsigned char bit) +{ + static unsigned long accu=1; + static unsigned long hamming_symbol; + + accu<<=1; + accu|=bit&1; + if (accu&(1UL<=FEC_SYMS){ + /* We couldn't write into the page, we need to make + * another one */ + new_file(); + hamming_symbol=0; + } + + /* Write the symbol into the page */ + for (shift=FEC_LARGEBITS-1;shift>=0;shift--) + write_channelbit(accu>>shift + , hamming_symbol+(FEC_LARGEBITS-1-shift) + *FEC_SYMS); + accu=1; + hamming_symbol++; + } +} + +void write_byte(unsigned char c) +{ + int bit; + + for (bit=7; bit>=0;bit--) + write_payloadbit(c>>bit); +} + +/* Prints the text at the bottom */ +/* Makes one output file. */ +void feed_data(void) +{ + int c; + + while((c=fgetc(input_stream))!=EOF){ + write_byte(c); + } + + /* Flush the FEC with zeroes */ + for (c=FEC_SMALLBITS-1;c;c--){ + write_payloadbit(0); + } + + dump_ary(); + fclose(output_stream); + +} + +void open_input_file(char *fname) +{ + input_stream=fopen(fname,"r"); + if (!input_stream){ + fprintf(stderr,"optar: cannot open input file %s: " + ,fname); + perror(""); + exit(1); + } + if (fseek(input_stream, 0, SEEK_END)){ + fprintf(stderr,"optar: cannot seek to the end of %s: " + ,fname); + perror(""); + exit(1); + } + n_pages=(((unsigned long)ftell(input_stream)<<3)+NETBITS-1) + /NETBITS; + if (fseek(input_stream,0, SEEK_SET)){ + fprintf(stderr,"optar: cannot seek to the beginning of %s: " + ,fname); + perror(""); + exit(1); + } +} + +/* argv format: + * 1st arg - input file + * 2nd arg(optional) - label and output filename base */ +int main(int argc, char **argv) +{ + + if (argc<2){ + fprintf(stderr,"Usage: optar [filename base]\n"); + exit(1); + } + open_input_file(argv[1]); + + if (argc>=3) file_label=base=(void *)argv[2]; + output_filename_buffer_size=strlen((char *)(void *)base)+1+4+1+3+1; + output_filename=malloc(output_filename_buffer_size); + if (!output_filename){ + fprintf(stderr,"Cannot allocate output filename\n"); + exit(1); + } + new_file(); + feed_data(); + fclose(input_stream); + free(output_filename); + return 0; +} diff --git a/optar.h b/optar.h new file mode 100644 index 0000000..b525405 --- /dev/null +++ b/optar.h @@ -0,0 +1,77 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MAX(x,y) ((x)>(y)?(x):(y)) + +#define BORDER 2 /* In pixels. Thickness of the border */ +#define CHALF 3 /* Size of the cross half. Size of the cross is CHALF*2 x CHALF*2. + */ +#define CPITCH 24 /* Distance between cross centers */ + +/* XCROSSES A4 65, US Letter 67. */ +#define XCROSSES 65 /* Number of crosses horizontally */ +/* YCROSSES A4 93, US Letter 87. */ +#define YCROSSES 93 /* Number of crosses vertically */ + +#define DATA_WIDTH (CPITCH*(XCROSSES-1)+2*CHALF) /* The rectangle occupied by + the data and crosses */ +#define DATA_HEIGHT (CPITCH*(YCROSSES-1)+2*CHALF) +#define WIDTH (2*BORDER+DATA_WIDTH) /* In pixels, including the border */ +/* In pixels, including the border and the label */ + +#define TEXT_WIDTH 13 /* Width of a single letter */ + +/* Definitions for seq2xy */ + +/* Properties of the narrow horizontal strip, with crosses */ +#define NARROWHEIGHT (2*CHALF) +#define GAPWIDTH (CPITCH-2*CHALF) +#define NARROWWIDTH (GAPWIDTH*(XCROSSES-1)) /* Useful width */ +#define NARROWPIXELS (NARROWHEIGHT*NARROWWIDTH) /* Useful pixels */ + +/* Properties of the wide horizontal strip, without crosses */ +#define WIDEHEIGHT GAPWIDTH +#define WIDEWIDTH (WIDTH-2*BORDER) +#define WIDEPIXELS (WIDEHEIGHT*WIDEWIDTH) + +/* Amount of raw payload pixels in one narrow-wide strip pair */ +#define REPHEIGHT (NARROWHEIGHT+WIDEHEIGHT) +#define REPPIXELS (WIDEPIXELS+NARROWPIXELS) + +/* Total bits before hamming including the unused */ +#define TOTALBITS ((long)REPPIXELS*(YCROSSES-1)+NARROWPIXELS) + +/* Hamming codes with parity */ +#define FEC_ORDER 1 /* Can be 2 to 5 inclusive. + 5 is 26/32, + 4 is 11/16, + 3 is 4/8, + 2 is 4/1 + 1 is golay codes */ +#if FEC_ORDER==1 +/* Golay */ +#define FEC_LARGEBITS 24 +#define FEC_SMALLBITS 12 +#else +/* Hamming */ +#define FEC_LARGEBITS (1<>16; + in^=in>>8; + in^=in>>4; + in^=in>>2; + in^=in>>1; + return in&1; +} + +/* Counts number of '1' bits */ +unsigned ones(unsigned long in) +{ + in-=((in>>1)&0x55555555UL); /* 2-bit groups result with max. 10 */ + in=(in&0x33333333UL)+((in&0xccccccccUL)>>2); /* 4-bit groups with + max. 100 */ + in+=in>>4; + in&=0x0f0f0f0fUL; /* 8-bit groups with max. 1000 */ + in+=in>>8; + in+=in>>16; + return in&0x3f; +} + + diff --git a/parity.h b/parity.h new file mode 100644 index 0000000..a8ce577 --- /dev/null +++ b/parity.h @@ -0,0 +1,7 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +extern unsigned long parity(unsigned long in); + +/* Counts number of '1' bits */ +extern unsigned ones(unsigned long in); + diff --git a/pgm2ps b/pgm2ps new file mode 100644 index 0000000..50497ef --- /dev/null +++ b/pgm2ps @@ -0,0 +1,17 @@ +#!/bin/sh +while [ $# -gt 0 ]; do + target=`echo "$1" | sed -e 's/\.pgm$/.ps/'` + echo Converting "$1" to "$target" +# We assume roughly 0.25 inch border (18) on each side. +# A4 is 595.27559 x 841.889763 (595 x 842) +# Letter is 8.5x11 inches or 612x792. + +# Change to 556.56x807.12+19.22+17.44 for A4 and +# 573.84x755.28+19.08+18.36 for US Letter. +# Don't forget to change XCROSSES and YCROSSES in optar.h and +# recompile. + convert -page 556.56x807.12+19.22+17.44 "$1" "$target" +# convert -page 573.84x755.28+19.08+18.36 "$1" "$target" + shift +done + diff --git a/unoptar.c b/unoptar.c new file mode 100644 index 0000000..5cd6e76 --- /dev/null +++ b/unoptar.c @@ -0,0 +1,1696 @@ +/* (c) GPL 2007 Karel 'Clock' Kulhavy, Twibright Labs */ + +#include /* printf */ +#include /* malloc */ +#include /* floor */ +#include /* memcpy */ +#include /* assert */ +#include /* libpng. Sometimes is in /usr/local/include/libpng/png.h, but that is taken + care of using -I/usr/local/include/libpng in the Makefile. */ + +#include "optar.h" +#include "parity.h" + +/* Crosses will be resynced with precision of FINESTEP pixels */ +#define FINE_CROSS_RESYNC +#define FINESTEP 0.25 +/* Define to disable repairing bit by Hamming codes */ + +#define MIN(x,y) ((x)<(y)?(x):(y)) + +/* Takes only unsigned integers, returns real value, if out of range returns + * white, doens't threshold*/ +#define getpixu(x,y) \ +((x)>=width||(y)>=height?0xff:ary[(x)+(y)*width]) + +/* Integers in corners */ +#define writepix(x,y,c) writepixu((unsigned)floor(x),(unsigned)floor(y),c) +/* If out of range, doesn't write anythinig. Integers are in pixel upper + * left corners. */ +#define writepixu(x,y,c) {if ((x)>1))/(width*height); + fprintf(stderr,"Average pixel value %u\n", average); +} + +/* Analyzes, determines the cut level */ +static void analyze_cutlevel(void) +{ + float white, black; + unsigned long black_pixels, white_pixels; + int i; + float white_rms, black_rms; /* At the end they will be RMS of the + distance from average */ +#define MAXITER 32 + int iter; /* max. MAXITER iterations */ + int lastcutlevel; + + fill_global_cutlevel=global_cutlevel=average; + + /* The second guess uses global_cutlevel from the first guess */ + for (iter=0;iterabs(y)){ + /* Horizontal */ + deg=180/M_PI*asin(y); + if (x<0) deg=180-deg; + }else{ + /* Vertical */ + deg=180/M_PI*asin(x); + if (y<0) deg=deg-90; + else deg=90-deg; + } + return deg; +} + +/* Puts it -180...+180 */ +static double normalize_angle(double a) +{ + return remainder(a,360); +} + +static void find_corners(void) +{ + int x,y; + + diag_scan(&x, &y, 0, 0, 1, 1); + if (x<0){ + static char failure []="failure_debug.pgm"; + fprintf(stderr,"Error: cannot find upper left corner\n"); +fail: + fprintf(stderr,"See failure_debug.pgm why.\n"); + memcpy(newary, ary, (unsigned long)width*height); + dump_newary(failure); + exit(1); + } + corners[0][0]=x; + corners[0][1]=y; + + diag_scan(&x, &y, width-1, 0, -1, 1); + if (x<0){ + fprintf(stderr,"Error: cannot find upper right corner\n"); + goto fail; + } + corners[1][0]=x+1; + corners[1][1]=y; + + diag_scan(&x, &y, 0, height-1, 1, -1); + if (x<0){ + fprintf(stderr,"Error: cannot find lower left corner\n"); + goto fail; + } + corners[2][0]=x; + corners[2][1]=y+1; + + diag_scan(&x, &y, width-1, height-1, -1, -1); + if (x<0){ + fprintf(stderr,"Error: cannot find lower right corner\n"); + goto fail; + } + corners[3][0]=x+1; + corners[3][1]=y+1; + + leftedge=MIN(corners[0][0],corners[2][0]); + rightedge=MAX(corners[1][0],corners[3][0]); + topedge=MIN(corners[0][1],corners[1][1]); + bottomedge=MAX(corners[2][1],corners[3][1]); + + hpixel=(corners[1][0]+corners[3][0] + -corners[0][0]-corners[0][0])/2.0/WIDTH; + vpixel=(corners[2][1]+corners[3][1] + -corners[0][1]-corners[1][1])/2.0/format_height; + fprintf(stderr,"One bit is %G horizontal pixels and %G " + "vertical pixels.\n", hpixel, vpixel); + + + { + unsigned vchalf, hchalf; + + /* Take only half to prevent spurious resync to an edge of the + * cross when the data mimic the other half of the cross. */ + hchalf=hpixel*CHALF*0.5; + vchalf=vpixel*CHALF*0.5; + + chalf=MIN(hchalf, vchalf); + /* Round to zero to make sure we don't catch any chaff */ + + /* Trim the cross by some fraction of input pixel to remove + * the area affected by crosstalk. */ + hchalf=hpixel*(CHALF-cross_trim); + vchalf=vpixel*(CHALF-cross_trim); + + chalf_fine=MIN(hchalf, vchalf); + } + + /* Calculate the pixel vectors */ + pixelhx=((double)corners[1][0]+(double)corners[3][0] + -(double)corners[0][0]-(double)corners[2][0])/2; + pixelhy=((double)corners[1][1]+(double)corners[3][1] + -(double)corners[0][1]-(double)corners[2][1])/2; + pixelvx=((double)corners[2][0]+(double)corners[3][0] + -(double)corners[0][0]-(double)corners[1][0])/2; + pixelvy=((double)corners[2][1]+(double)corners[3][1] + -(double)corners[0][1]-(double)corners[1][1])/2; + + /* Normalize the horizontal vector (which may not be exactly + * horizontal */ + normalize_vector(&pixelhx, &pixelhy); + /* Normalize the vertical vector (which may not be exactly + * vertical */ + normalize_vector(&pixelvx, &pixelvy); + fprintf(stderr,"Input horizontal pixel vector %G,%G, vertical %G,%G." + " skew %G deg, perpendicularity %G deg.\n", + pixelhx, pixelhy, pixelvx, pixelvy + ,normalize_angle(angle(pixelhx, -pixelhy) + +angle(pixelvx, -pixelvy)+90)/2 + ,angle(pixelhx, -pixelhy)-angle(pixelvx, -pixelvy)); + + { + unsigned long bytes=(long)(4*chalf+1)*(4*chalf+1) + *sizeof*search_area; + search_area=malloc(bytes); + if (!search_area){ + fprintf(stderr, + "Cannot allocate search area of %lu bytes\n", + bytes); + exit(1); + + } + } + fprintf(stderr,"Allocating search area of %u x %u (%u) pixels.\n", + chalf<<1, chalf<<1, (chalf*chalf)<<2); + + fprintf(stderr,"Upper corners at %lu, %lu and %lu, %lu,\n" + "lower corners at %lu, %lu and %lu, %lu.\n" + "Cross half for searching is %d x %d input pixels.\n", + corners[0][0], corners[0][1], corners[1][0], corners[1][1], + corners[2][0], corners[2][1], corners[3][0], corners[3][1], + chalf, chalf); + +} + +static double bilinear(double ul, double ur, + double ll, double lr, + double hpar, double vpar) +{ + double u,l; /* Upper, lower */ + + u=ur*hpar+ul*(1-hpar); + l=lr*hpar+ll*(1-hpar); + return l*vpar+u*(1-vpar); +} + +static float bilinearf(float ul, float ur, + float ll, float lr, + float hpar, float vpar) +{ + float u,l; /* Upper, lower */ + + u=ur*hpar+ul*(1-hpar); + l=lr*hpar+ll*(1-hpar); + return l*vpar+u*(1-vpar); +} + +/* x,y with integers in centers of pixels */ +static float get_pixel_interp(double x, double y) +{ + unsigned xi, yi; /* Integer versions, rounded down */ + + /* Supports even extrapolation, but should be never necessary */ + if (x<0) xi=0; else xi=floor(x); + if (y<0) yi=0; else yi=floor(y); + + /* Make it faster, only little precision needed. */ + return bilinearf(getpixu(xi,yi), getpixu(xi+1,yi), + getpixu(xi,yi+1),getpixu(xi+1,yi+1), + x-xi, y-yi); +} + +/* Samples pixels and performs correction(s) */ +static float pixel_correct_sample(double x, double y) +{ + float val; + float avg; /* First sum, later average */ + double hdist, vdist; + + hdist=hpixel*unsharp_dist; + vdist=vpixel*unsharp_dist; + + avg=get_pixel_interp( + PSHIFTX(x, -hdist, 0), + PSHIFTY(y, -hdist, 0)); + avg+=get_pixel_interp( + PSHIFTX(x, hdist, 0), + PSHIFTY(y, hdist, 0)); + avg+=get_pixel_interp( + PSHIFTX(x, 0, vdist), + PSHIFTY(y, 0, vdist)); + avg+=get_pixel_interp( + PSHIFTX(x, 0, -vdist), + PSHIFTY(y, 0, -vdist)); + avg/=4; + + + val=get_pixel_interp(x,y); + val+=unsharp_mask*(val-avg); /* Emphasize the distance from average */ + return val; +} + +/* Returns difference from global_cutlevel. Integers in centers of pixels. Interpolates + * for nonintegral coordinates. */ +static float diffpix(double x, double y) +{ + return get_pixel_interp(x,y)-global_cutlevel; +} + +/* Calculates a correlation with a cross. x and y are coords of the cross + * center with integers in UL corners of pixels. */ +static float cross_correl(double x, double y) +{ + double dx, dy; + float sum =0; + + /* -0.5 for conversion corners -> centers, +0.5 for conversion + * cross center -> sample point 1/2 pixel away from the cross + * center -> No addition at all */ + + for (dx=0;dx=0); + assert (xpos<=4*chalf); + assert (ypos>=0); + assert (ypos<=4*chalf); + + return search_area[ypos*(4*chalf+1)+xpos]; +} + +/* xpos says the cross offset. 0,0 means at the original position from around + * which the search_area was loaded. The range is -chalf to chalf + * (inclusive). The input must be in that range, otherwise crash */ +static float cross_correl_search(int xpos, int ypos) +{ + float sum; + + assert(xpos>=-chalf); + assert(xpos<=chalf); + assert(ypos>=-chalf); + assert(ypos<=chalf); + + /* Normalize the xpos and ypos to mean the cross center in array + * indices. 0 means array left edge, 2*chalf array center, 4*chalf array + * right edge. */ + + xpos+=2*chalf; + ypos+=2*chalf; + + /* Center */ + sum=-4*getsearch(xpos,ypos); + + /* Middles of sides */ + sum+=2*( + getsearch(xpos-chalf, ypos)+ + getsearch(xpos+chalf, ypos)+ + getsearch(xpos, ypos-chalf)+ + getsearch(xpos, ypos+chalf) + ); + + /* Corners */ + sum-=( + getsearch(xpos-chalf, ypos-chalf)+ + getsearch(xpos-chalf, ypos+chalf)+ + getsearch(xpos+chalf, ypos-chalf)+ + getsearch(xpos+chalf, ypos+chalf) + ); + + return sum; +} + +/* After this, pixel [0][0] means integral from [0][0] to [1][1] (!), etc. */ +static void integrate_search_area(void) +{ + int x, y; + float *ptr; + + /* Horizontal integration */ + ptr=search_area; + for (y=0;y<=4*chalf;y++){ + ptr++; + for (x=1;x<=4*chalf;x++){ + ptr[0]+=ptr[-1]; + ptr++; + } + } + + ptr=search_area+4*chalf+1; + + /* Vertical integration */ + for (;ptrglobal_cutlevel){ + /* White */ + white_rms+=(val-global_cutlevel)*(val-global_cutlevel); + whitepixels++; + }else if (valmax) + { + max=result; + xoffmax=xoff; + yoffmax=yoff; + } + } + xmax=PSHIFTX(coordpair[0], xoffmax, yoffmax); + ymax=PSHIFTY(coordpair[1], xoffmax, yoffmax); + +#ifdef FINE_CROSS_RESYNC +#define HALFRANGE (0.5/FINESTEP) /* 0.5 means 0.5 of small input pixel - no + need to search more since then it would be + caught by the neighbouring coarse search + try. */ + /* Load the fine search initial maximum position */ + xoffmax=0; + yoffmax=0; + + /* This must be here since cross_correl and cross_correl_search + * return the result scaled by a different factor. */ + max=cross_correl(xmax,ymax); + + /* Fine search, FINESTEP pixels/ step. Counting in 0.25 steps */ + for (xoff=-HALFRANGE;xoff<=HALFRANGE;xoff++) + for (yoff=-HALFRANGE;yoff<=HALFRANGE;yoff++){ + /* This is not using the search area anymore! */ + result=cross_correl( + PSHIFTX(xmax, (double)xoff*FINESTEP + ,(double)yoff*FINESTEP) + ,PSHIFTY(ymax, (double)xoff*FINESTEP + ,(double)yoff*FINESTEP)); + if (result>max){ + max=result; + xoffmax=xoff; + yoffmax=yoff; + } + } + /* Save the fine search result */ + xmax=PSHIFTX(xmax, (double)xoffmax*FINESTEP, (double)yoffmax*FINESTEP); + ymax=PSHIFTY(ymax, (double)xoffmax*FINESTEP, (double)yoffmax*FINESTEP); + +#endif /* FINE_CROSS_RESYNC */ + + /* Store the output */ + coordpair[0]=xmax; + coordpair[1]=ymax; +} + +static void sync_crosses(void) +{ + unsigned cx,cy; /* Cross number */ + double rightx, righty, downx, downy; /* Two cross pitch vectors */ + + /* Calculate the estimated cross pitch vectors */ + rightx=((double)corners[1][0]+corners[3][0]-corners[0][0]-corners[2][0]) + /2*CPITCH/WIDTH; + righty=((double)corners[1][1]+corners[3][1]-corners[0][1]-corners[2][1]) + /2*CPITCH/WIDTH; + downx=((double)corners[2][0]+corners[3][0]-corners[0][0]-corners[1][0]) + /2*CPITCH/format_height; + downy=((double)corners[2][1]+corners[3][1]-corners[0][1]-corners[1][1]) + /2*CPITCH/format_height; + + /* Load the upper left cross with an estimate of it's position */ + crosses[0][0][0]=bilinear( + corners[0][0], corners[1][0], + corners[2][0], corners[3][0], + (double)(BORDER+CHALF)/WIDTH, + (double)(BORDER+CHALF)/format_height); + crosses[0][0][1]=bilinear( + corners[0][1], corners[1][1], + corners[2][1], corners[3][1], + (double)(BORDER+CHALF)/WIDTH, + (double)(BORDER+CHALF)/format_height); + + fprintf(stderr,"Finding crosses (%u lines), numbers indicate " + "individual cutlevels:\n", YCROSSES); + + for (cy=0;cy0){ + /* Copy from left */ + crosses[cx][cy][0]=crosses[cx-1][cy][0]+rightx; + crosses[cx][cy][1]=crosses[cx-1][cy][1]+righty; + }else if (cy>0){ + /* Copy from above */ + crosses[cx][cy][0]=crosses[cx][cy-1][0]+downx; + crosses[cx][cy][1]=crosses[cx][cy-1][1]+downy; + }/* else already preloaded */ + resync_cross(crosses[cx][cy]); + cross_stats(cx, cy); + } + putc('\n',stderr); + } +} + +/* x,y coords in bit matrix. 0,0 is in the upper left cross UL corner. + * Returns pixel position with integers in centers of pixels. Interpolates + * also the cutlevel */ +static void bit_coord(double *xout, double *yout, float *cutlevel, + int x, int y) +{ + unsigned cx, cy; /* Cross number */ + double xd, yd; + double xrem, yrem; + + /* First find the cross numbers */ + /* Division of negative numbers is probably undefined in C! */ + if (xXCROSSES-2) cx=XCROSSES-2; + if (cy>YCROSSES-2) cy=YCROSSES-2; + + /* Now subtrack cross coordinate */ + x-=cx*CPITCH+CHALF; + y-=cy*CPITCH+CHALF; + /* x,y now the remainders. Can be negative or more than CPITCH! */ + + /* Calculate double precision remainders about from 0 to 1 (not always) */ + xrem=((double)x+0.5)/CPITCH; + yrem=((double)y+0.5)/CPITCH; + + xd=bilinear( + crosses[cx][cy][0], crosses[cx+1][cy][0], + crosses[cx][cy+1][0],crosses[cx+1][cy+1][0], + xrem, yrem); + yd=bilinear( + crosses[cx][cy][1], crosses[cx+1][cy][1], + crosses[cx][cy+1][1],crosses[cx+1][cy+1][1], + xrem, yrem); + if (cutlevel){ + *cutlevel=bilinearf( + cutlevels[cx][cy], cutlevels[cx+1][cy], + cutlevels[cx][cy+1],cutlevels[cx+1][cy+1], + xrem, yrem); + } + /* xd, yd are now with integers in UL corners of pixels */ + xd-=0.5; + yd-=0.5; + /* xd, yd are now with integers in centers of pixels */ + + *xout=xd; + *yout=yd; +} + +static void read_payload_bit(unsigned char bit) +{ + static unsigned accu=1; + + accu<<=1; + accu|=bit&1; + if (accu&(1<<8)){ + putchar(accu&0xff); + accu=1; + } +} + +#if FEC_ORDER !=1 +/* Cuts out given bit and shifts the upper part */ +static unsigned long shrink(unsigned long in, unsigned bitpos) +{ + unsigned long high; + in&=~(1<>1)|in; +} +#endif + +static void mark_bad_bit(unsigned x, unsigned y, int dir) +{ + int size=floor(2*sqrt(hpixel*vpixel)+0.5); + unsigned u; + int i; + int v=dir?0:255; + + if (dir){ + /* To 1, means black dirt. Upper left edge. */ + for (u=0;u=0); + switch(dir){ + case 0: delim='\''; break; + case 1: delim=','; break; + default: delim=':'; break; + } + fprintf(stderr,"%ld%c%ld ",(long)xd, delim, (long)yd); +} + +static void print_badbit_finish(void) +{ + if (bad_total){ + fprintf(stderr,"\n%lu bits bad from %lu, bit error rate %G%%. " + "%G%% black dirt, %G%% white dirt and " + "%lu (%G%%) irreparable.\n", + bad_total, + USEDBITS, + 100*(double)(bad_total)/USEDBITS, + 100*(double)bad_01/(bad_total), + 100*(double)bad_10/(bad_total), + irreparable, + 100*(double)irreparable/(bad_total)); + } + else fprintf(stderr,"No bad bits!\n"); +#if FEC_ORDER == 1 + fprintf(stderr,"Golay stats\n" + "===========\n" + "0 bad bits %lu\n" + "1 bad bit %lu\n" + "2 bad bits %lu\n" + "3 bad bits %lu\n" + "4 bad bits %lu\n" + "total codewords %lu\n" + , golay_stats[0] + , golay_stats[1] + , golay_stats[2] + , golay_stats[3] + , golay_stats[4] + , golay_stats[0]+golay_stats[1] + +golay_stats[2]+golay_stats[3]+golay_stats[4]); +#endif +} + +void golay_bad_bits(unsigned long right, unsigned long wrong, unsigned + long symno) +{ + int bit; /* 23 MSB, 0 LSB */ + + for (bit=23; bit>=0;bit--){ + if ((right^wrong)&(1UL<>bit)&1); + } + } + + +} + +static unsigned long ungolay(unsigned long in, unsigned long symno) +{ + unsigned data=in>>12; + + if (golay(data)==in){ + golay_stats[0]++; + return data; /* No error */ + } + + /* Search for a symbol that differs in max. 3 positions */ + for (data=0;data<(1<<12);data++){ + unsigned n_ones; + n_ones=ones(golay_codes[data]^in); + if (n_ones<=3){ + /* Found the right answer */ + golay_bad_bits(golay_codes[data],in, symno); + golay_stats[n_ones]++; + return data; + } + + } + + /* "data" is not valid anymore now! */ + + /* Irreparable */ + { + int badbit; + + fputc('\n',stderr); + for (badbit=0;badbit<24;badbit++) + print_badbit(symno, badbit, 2); + fprintf(stderr,"!\n"); + irreparable+=4; + bad_total+=4; + golay_stats[4]++; + return in>>12; + } + +} + +#if FEC_ORDER !=1 +/* symno is just to figure out xy when printing broken bits. Only the + * lowest FEC_LARGEBITS are taken into account on input. */ +static unsigned long unhamming(unsigned long in, unsigned long symno) +{ + unsigned bugpos=0; + + /* Split the shift to make sure that it works even it FEC_LARGEBITS + * is the full size of the type */ + in&=(1UL<<(FEC_LARGEBITS-1)<<1)-1; +#if FEC_ORDER>=5 + bugpos|=parity(in&0xffff0000)<<4; +#endif +#if FEC_ORDER>=4 + bugpos|=parity(in&0xff00ff00)<<3; +#endif +#if FEC_ORDER>=3 + bugpos|=parity(in&0xf0f0f0f0)<<2; +#endif + bugpos|=parity(in&0xcccccccc)<<1; + bugpos|=parity(in&0xaaaaaaaa); + if (bugpos){ + in^=1UL<=5 + in=shrink(in,16); +#endif +#if FEC_ORDER>=4 + in=shrink(in,8); +#endif +#if FEC_ORDER>=3 + in=shrink(in,4); +#endif + in>>=3; + return in; +} +#endif /* FEC_ORDER */ + +static void read_hamming_bit(unsigned char input, unsigned long symno) +{ + static unsigned accubits; + static unsigned long accu; + + accu<<=1; + accu|=input&1; + accubits++; + if (accubits>=FEC_LARGEBITS){ + int shift; +#if FEC_ORDER == 1 + accu=ungolay(accu, symno); +#else + accu=unhamming(accu, symno); +#endif /* FEC_ORDER */ + for (shift=FEC_SMALLBITS-1;shift>=0;shift--) + read_payload_bit(accu>>shift); + accu=0; + accubits=0; + } +} + +void reset_stats(void) +{ + bad_01=0; + bad_10=0; + bad_total=0; + irreparable=0; + memset(golay_stats, 0, sizeof golay_stats); +} + +static void read_syms(void) +{ + unsigned long hamming_sym; /* Hamming symbol sequence number */ + unsigned bit; + unsigned long seq; + int x,y; /* 0,0 is upper left pixel of upper left cross */ + double xcoord, ycoord; /* Integers in centers */ + float pixval; + float local_cutlevel; + + reset_stats(); + + for (hamming_sym=0;hamming_sym255) writeval=255; + else if (writeval<0) writeval=0; + writeval^=255; + + writepix(xcoord+0.5, ycoord+0.5, + writeval); + /* Make a debug dot */ + } + + read_hamming_bit(pixval0;yctr--){ + *dest++=*src++; /* Leftmost pixel */ + for (xctr=width-2;xctr>0;xctr--){ + val=src[0]<<2; + val+=(src[-1]+src[1]+*(src-width)+src[width])<<1; + val+=*(src-1-width)+*(src-width+1) + +src[width-1]+src[width+1]; + val=(val+8)>>4; /* 4+2+2+2+2+1+1+1+1=16 */ + *dest++=val; + src++; + } + *dest++=*src++; /* Rightmost pixel */ + } + memcpy(dest,src,width); /* Bottommost row */ + memcpy(ary,newary,width*height); + fprintf(stderr,"%d ",cycles); + } + if (!blur_cycles) memcpy(newary,ary,width*height); + else fprintf(stderr,"\n"); +} + +/* Shifts half pixel right and down! */ +static void max(void) +{ + unsigned char *ptr, *end, *linestart; + unsigned long yctr; + + ptr=ary+(unsigned long)width*height; + for (yctr=height;yctr;yctr--){ + linestart=ptr-width; + ptr--; + for (; ptr>linestart; ptr--) + ptr[0]=MAX(ptr[0],ptr[-1]); + } + + end=ary+width; + for (ptr=ary+(unsigned long)width*height-1;ptr>=end; ptr--) + ptr[0]=MAX(ptr[0],*(ptr-width)); + +} + +/* Shifts half pixel left and up! */ +static void min(void) +{ + unsigned char *ptr; + unsigned char *end; + unsigned long yctr; + + for (ptr=ary,yctr=height;yctr;yctr--){ + for (end=ptr+width-1;ptrx=x; + wptr->y=y; + wptr++; + if (wptr>=que_end) wptr=que; + if (wptr==rptr){ + fprintf(stderr,"unoptar: Floodfill que overflowed. Search " + "for \"que=malloc\" in the program and increase the " + "size.\n"); + exit(1); + } +} + +/* 1 OK, 0 empty */ +static int que_read(unsigned *x, unsigned *y) +{ + if(wptr==rptr) return 0; /* Empty */ + *x=rptr->x; + *y=rptr->y; + rptr++; + if (rptr>=que_end) rptr=que; + return 1; +} + +static void init_que(void) +{ + rptr=que; + wptr=que; +} + +static void try_copy_white(unsigned x, unsigned y, char test) +{ + unsigned char *destptr; + + if (test&&ary[(unsigned long)y*width+x]>1,0,1); + fill(width-1,0,1); + fill(0,height>>1,1); + fill(0,height-1,1); + fill(width-1, height-1,1); + fill(width-1, height>>1,1); + fill(width>>1, height-1,1); + fprintf(stderr,"white border identified, "); + fill(width>>1, height>>1, 0); + fprintf(stderr,"data area identified, "); + /* Now white parts and the data area are filled with 0xff in newary. */ + erase_dirt(); + free(que); +} + +/* Produces already linear output! */ +void read_png(void) +{ + png_structp png_ptr; + png_infop info_ptr; + double gamma; /* gamma from the info in the file */ + int y1,number_of_passes; + unsigned char **ptrs; + + png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + info_ptr=png_create_info_struct(png_ptr); + png_init_io(png_ptr,input_stream); + png_read_info(png_ptr, info_ptr); + width=png_get_image_width(png_ptr,info_ptr); + height=png_get_image_height(png_ptr,info_ptr); + fprintf(stderr,"Input %u x %u pixels, taking %G megabytes for 2 " + "framebuffers.\n" + ,width, height, 2*(float)width*height/1e6); + if (png_get_gAMA(png_ptr,info_ptr, &gamma)) + png_set_gamma(png_ptr, 1.0, gamma); + else + png_set_gamma(png_ptr, 1.0, 0.454545); /* Default gamma */ + { + int bit_depth; + int color_type; + + color_type=png_get_color_type(png_ptr, info_ptr); + bit_depth=png_get_bit_depth(png_ptr, info_ptr); + if (color_type==PNG_COLOR_TYPE_GRAY){ + if (bit_depth<8){ + png_set_expand(png_ptr); + } + if (bit_depth==16){ + png_set_strip_16(png_ptr); + } + } + if (color_type==PNG_COLOR_TYPE_PALETTE){ + png_set_expand(png_ptr); + png_set_rgb_to_gray(png_ptr,1, -1,-1); + /* Default weights to be used */ + } + if (color_type & PNG_COLOR_MASK_ALPHA){ + png_set_strip_alpha(png_ptr); + } + if (color_type==PNG_COLOR_TYPE_RGB || + color_type==PNG_COLOR_TYPE_RGB_ALPHA){ + png_set_rgb_to_gray(png_ptr, 1, -1, -1); + /* Default weights to be used */ + } + + } + /* If the depth is different from 8 bits/gray, make the libpng expand + * it to 8 bit gray. + */ + number_of_passes=png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr,info_ptr); + ary=malloc((unsigned long)width*height); + newary=malloc((unsigned long)width*height); + if (!(ary&&newary)){ + fprintf(stderr,"Cannot allocate framebuffers.\n"); + exit(1); + } + ptrs=malloc(height*sizeof(*ptrs)); + if (!ptrs){ + fprintf(stderr + ,"Cannot allocate %lu bytes for auxilliary buffer\n" + ,height*(unsigned long)(sizeof*ptrs)); + exit(1); + } + for (y1=0;y1=9999){ + fprintf(stderr,"unoptar: Too many pages - 10,000 or " + "more.\n"); + exit(1); + } + snprintf(longer, alloclen-6,"%s_%04u.png", + base, ++file_number); + /* 6 for "_debug" */ + + input_stream=fopen(longer, "r"); + if (!input_stream) + { + if (file_number==1){ + /* We didn't have any files! */ + fprintf(stderr,"unoptar: cannot open %s: " + ,longer); + free(longer); + perror(""); + exit(1); + }else{ + free(longer); + return; + } + } + process_file(longer); /* Clobbers longer! Automatically closes + input_stream! */ + } + +} + +static void parse_format(char *format) +{ + unsigned dummy; + + sscanf(format,"%u-%u-%u-%u-%u-%u-%u-%u", + &dummy, + &dummy, + &dummy, + &dummy, + &dummy, + &dummy, + &dummy, + &text_height); + fprintf(stderr,"Format: text height=%u\n", text_height); +} + +/* argv: + * input filename base (mandatory). For example "base" will produce + * base_0001.png and base_0001_debug.pgm. + * text height (optional, defaults to 24) + */ +int main(int argc, char **argv) +{ + if (argc<3){ + fprintf(stderr,"usage: unoptar " + " \n"); + exit(1); + } + + parse_format(argv[1]); + /* This must after all dimension-related parameters are decoded. */ + init_dimensions(); + + print_chan_info(); + process_files(argv[2]); + + return 0; +}