         Q L   H A C K E R ' S   J O U R N A L
      ===========================================
           Supporting  All  QL  Programmers
      ===========================================
         #17                        April 1994

    The QL Hacker's Journal (QHJ) is published by Tim
Swenson as a service to the QL Community.  The QHJ is
freely distributable.  Past issues are available on disk,
via e-mail, or via the Anon-FTP server, garbo.uwasa.fi.
The QHJ is always on the look out for article submissions.

        QL Hacker's Journal
     c/o Tim Swenson
     5615 Botkins Rd
     Huber Heights, OH 45424 USA
     (513) 233-2178
     *** swensotc@ss2.sews.wpafb.af.mil
     tswenson@dgis.dtic.dla.mil

     *** Note new E-Mail address


EDITOR'S FORUM

   As much as I want the QHJ to come out about every other
month, It's slowly becoming a quarterly.  Between work,
family, and other hobbies, the QHJ is getting little time.
Luckily, this month most of the articles are user
submitted.  In fact, this is the first time that more than
one article in a month has been user submitted.  A big
thanks to Franz Herrmann, Herb Schaaf, and Mike Fink.

   After the last QHJ came out, I broadcast an offer from
Bob Dyl, publisher of International QL Report, to provide a
free sample copy of the IQLR.  Fourteen readers responded
to the offer.  By now all of those that responded should
have thier issue.  As expected, most of the responses came
from Europe, but I did get one from the US.

   For the record, Herb Schaaf was the taker in the offer
of "The Elements of Programming Style" from the last issue.

   Coming up on 14 May, is the 2nd annual Miracle in
Newport show, in Newport, Rhode Island.  I plan to attend
again this year.  I getting a ride with Paul Holmgren
(Mechanical Affinity) and will be there for the show (but
little else).  We'll be leaving early Sunday morning.  If
you are going to be there, drop by and see me.  I'll be in
my QHJ T-shirt.  I'll bring along some extra issues and
some disks with all of the past issues on them.

   For those following the legal side of programming, there
was a good article in the May 94 issue of Dr Dobbs Journal
discussing the recent lawsuit between Microsoft and Stac
Electronics.  The article did a great job a covering the
facts fully and easily.  If you can't get DDJ near you, I
can copy the article and pass it along.

   In the April issue of DDJ, Michael Swaine discusses Risc
chips and mentions some history of the Acorn Risc chip and
the British microcomputer scene.  Of course, he mentions
Sinclair.  It's nice to know that the mainstream press
still remembers Sinclair.


READERSHIP SURVEY

   I recieved a total of 11 responses the the Readership
Survey.  Some of the surveys came with some long comments
that were good to hear.

What languages do you program in?

   C (8 votes), Basic (7 votes) and Assembly (6 votes) were
the highest answers.  There were a few votes for Pascal,
XLISP, Prolog, Forth, and Postscript.  I'd like to see more
assembly, but I'm am not an assembly programer.  Any
volunteers?

What compiler/interpreter do you use?

   As expected C68 got the most votes (7).  QLiberator got
3 votes. The test of a packages got 2 or less votes.  A
number of assemblers that I had not heard of were
mentioned.

What languages would you like to see covered?

   C and Assembly both got 3 votes.  Basic, Pascal,
Postscript, and OOP got 1 vote.  I might be able to rope
someone into doing some articles using XLISP for Object
Oriented Programming (OOP).

State your areas of interest in programming?

   This was varied.  Some wanted low-level, including
hardware.  Some wanted high-level programming.  Other
interests were Pointer Interface, fax software, graphics,
math, compression, communications, encryption, and
utilities.  Some of these areas may be grabbed from other
mags and ported to the QL.

How much time do you program?

   Thesse responses were varies.  Any where from a half
hour a day, to 4 hrs a day.  Most said that it went in
spurts.  They did  not program that many hours every day.

Do you program proffessionally?

   Four people said that they did program professionally.
Some hoped to.  Some people were still in college.

What level of training have you had in programming?

   Of all the questions in the survey, this one seemed to
confuse a few people.  They responded by not knowing what
the question was asking.  I chalk it up to a language
barrier thing.  6 people said that they were had computer
classes in college.  3 said that they had no teaching at
all.

What is your favorite text editor?

   As expected, the highest votes went to QED (6 votes).
Emacs got 2 votes.  DME, SEDIT, ED, MasterSpy, and QDIII
each got 1 vote.

QHJ Related Questions:

What languages would you like to see covered?

   Only after the survey went out I noticed this was a
repeat of a previous question.  Even then, some people
still answered, and, as expected, the answer was the same
(C and Assembly).

What areas of programming would you like to see covered?

   This also was a repeat question.  Refer to the first
question for the responses.

Do you prefer code intensive articles?

   Not too many responded to this.  Two said yes, one said
no.

Do you prefer more verbose articles?

   This question too was not answered by many.  One each
said yes and no.

Do you prefer the hard-copy or the electronic version?

   Six readers said that they  prefer the electronic, one
said the hard copy and one said that he likes it on disk.

How many persons read your copy of the QHJ?

   Most said that no one read their copy, but one said one
other person did, and one said that two other persons did.
I know some people get the QHJ via BBS's and not directly
from me.

Would you be interested in a QHJ T-shirt?

   This one was a tie with four answering yes and no.  The
reason I asked this was to see if I should print up some
more T-shirts.  The last set was done by a old friend.
Once he finished his current move, I may ask him to do some
more.

QL Enviroment Questions

Do you use the Pointer Environment?

   Six said yes, and 2 said no.

Do you use Toolkit II?

   Ten responded with yes.  A few said that they felt TKII
was almost an integral part of QDOS.  Personally, I load it
only when I need it and try not to rely on it in
programming.  Since I still have a JSU rom system, I like
to program so those with a plain QL can use my programs.

Do you use other computers?

   Nine readers said yes.  Obviously, most QHJ readers are
using other computers, either at work or home.  I'm not one
that feels the QL or QDOS is the only computer to use.  I
would not recommend the QL to the average person.  If a
person wanted a neat computer to tinker with and learn on,
then I'd recommend the QL.  MS-DOS is really just CP/M,
Unix is more fun and hackable, but the QL has character.

   I am glad that I did this survey.  I gave me a little
more insight into the people that read the QHJ.  Gave me an
idea of what readers like and dislike.  If you did not
respond to the survey and want to make a few comments, I'm
always ready to hear any suggestions or comments.  I don't
want to produce something that no one will read.


C PORTABILITY
   BY FRANZ HERRMANN

   This article is dedicated to show some rather randomly
chosen aspects of portable programming with C68 on the QL.

   A 'C' program is fully portable if the source text can
be compiled  on any operating system which provides a
standard compiler (usually the standard is defined by K&R
or ANSI) without any changes at all. Although the 'C'
language is specifically designed to allow hardware and
operating system independent programming, full portability
is often impossible to achieve. That is because there are
no generally accepted interfaces to more advanced harware
(eg. graphics, sound) and some obsolete but very common
operating systems (namely MS/DOS) pose unpractical
limitations, such as file name layout and memory
allocation. However, 'C' is superior in portability to
other popular languanges in that from the early beginning
the standard defined exact library specifications for
input/output purposes including file handling, string
handling, memory management, mathematics including
representation of numbers, error trapping, system date
handling and more.

   Let's come to the example program and go into some
details:

   Programs (not just those programmed in 'C') are often
organised in modules if they become large. This speeds up
production of executable code because with the help of the
MAKE utility, only those modules which have been altered
are recompiled. Each source module is held in a single
file, and is a good idea to give each of them a small
header that gives a brief description of the module, date
and author of the program. Also changes could be documented
in detail there.

   At the top of a program or module are virtually always
#include lines which tell the preprocessor to merge other
files, for example header files containing prototypes for
library function (thus allowing the compiler to detect the
wrong use of a function). If your program should be
portable then only #include those header files which are
explicitely mentioned in K&R -if you are not merging your
own which are of course supplied with the source. You will
find that K&R uses a dot to seperate the extention from the
base file name (eg. stdio.h) and that this is not the case
for C68 where an underscore is used (eg. stdio_h).
Nevertheless, always use the dot in your source, C68 will
translate that correctly.

   If you feel necessary to use system specific calls or
declarations than you can either put it in a seperate file
(not used here) or put the relevant source lines in an
#ifdef...#endif clause; the preprocessor will then make
these lines invisible to the compiler if the condition
(here: 'QDOS' defined) if not satisfied.

   Every 'C' program has to contain the main() function
somewhere. Always declare this as integer, even if you do
not intend to return anything to the program which started
started yours. ANSI clearly forbids any else but integer.
Recently, C68 was modified to allow 'void' and others as
well (I forgot why but I think it had something to do with
implementation of ANSI prototyping) but it is best if you
ignore this.

   The example uses several printf() calls to write
messages. They will always mention the program name
(argv[0]) because if a program is running in a multitasking
environment from a shell, ie. if is runs concurrently with
other programs and has to share a scrolling text window
with them, it might be difficult to identify the origin of
a message. In the example, this should be not necessary
because it is very fast in operating (or my QL with the
speedy Gold Card).

   By the way, you may wonder why all printf()s are
preceeded by (void). It has nothing to do with portability:
printf() is an integer that returns the number of actually
written characters, since I have no need for these values,
I am ignoring them and the compiler will therefore produce
warnings if these are not suppressed.

   I personally use C68 at the highest warning level, level
six. It can activated from CC with the '-Qwarn=6' option,
but I avoided this in the example MAKEFILE; I have set the
environment variable 'C68' set to '-warn=6 -error=3
-maxerr=4' in my BOOT file. You may find the warning
annoying, but they help a lot to detect mistakes before
they can cause crashes. However, the compiler of C68 v4.12,
c68 v4.4 beta, issues one particuliar warning which I am
ignoring with good reason: "assignment in conditional
context".

   The 'y' variable has been introduced to seperate
calculation from the printf() that cares for output of the
result. On some systems the line may be not be flushed and
multitasking stopped until calculation is complete, ie.
until the full line can be written.

   The use of DBL_EPSILON allows the compiler to adapt the
program to the precision of floating point calculation by
replacing DBL_EPSILON by a constant describing this
precision. With very bad floating point packages (not C68!)
it might happen that the while() loop in the root()
sub-routine will never stop. Blame the compiler!

   The if() condition at the 'default' label in the
switch() could be replaced by a ENOERR label in the
switch(), but this is not mentioned in K&R, 2nd edition, so
this construction here is safer.

   It is recommended that you keep lines not longer than 70
to a maximum of 80 characters, that makes it easier to send
them by email without some communication software wrapping
lines. Ok, that's not important for portability.

   MAKEFILEs are not portable but you can at least simplify
porting if you make file name suffix flexible as in the
example makefile. The -L$(LIB_DIR) corrects an
inconvenience in the current release of C68, (the linker
does not read the LIB_DIR environment variable) I am sure
that this will be fixed one of the next C68 releases. At
time of writing, version 3.05 is up-to-date.


The example program (root_c):

/*
 *  Demonstration of a simple algorithm to find the square
 *  root of real non-negative numbers, already known to
 *  the old Greek and Babylonian cultures.
 *
 *                    Franz Herrmann, 9/5/93
 */


#include <stdio.h>      /* printf() */
#include <errno.h>      /* errno, EDOM, ERANGE */
#include <float.h>      /* DBL_EPSILON */
#include <stdlib.h>     /* atof() */

#ifndef ABS
#define ABS(x) ((x) < 0 ? -(x) : (x))
#endif

#ifdef QDOS
char _prog_name[] = "ROOT";
#endif

/* #define VERBOSE */


double root (double x)
{
    double a = 0.1;
            /* estimation for square root of x */
    double tmp;
            /* temporary variable */
    double delta = 1.0;
            /* difference describing process */

    while (delta > DBL_EPSILON) {
        tmp = a;
        a = (a + x/a) / 2.0;
        delta = ABS(tmp - a);
        #ifdef VERBOSE
        (void) printf("delta = %5.20f\n", delta);
        #endif
    }

    return a;
}


int main (int argc, char *argv[])
{
    double x;   /* argument as floating point number */
    double y;   /* result */

    if (argc != 2) {
        (void) printf("%s: Usage: root <x>\n", argv[0]);
        return -1;
    }

    if ((x = atof(argv[1])) < 0) {
        (void) printf("%s: Negative arguments not allowed.
            \n", argv[0]);
        return -1;
    }

    switch (errno) {
      case EDOM:   (void) printf("%s: Invalid
                       argument.\n", argv[0]);
                   return -1;

      case ERANGE: if (x == 0.0)
                   (void) printf("%s: Range %srflow.\n",
                    (x == 0.0 ? "unde" : "ove") , argv[0]);
                   return -1;

      default:     if (errno) {
                    (void) printf("%s: Unknown error %d.\n",
                      argv[0], errno);
                      return -1;
                   }
          break;
    }

    (void) printf("%s: Calculating...\n", argv[0]);

    y = root(x);
    (void) printf("%s: The square root of %f is %f.\n",
       argv[0], x, y);

    return 0;
}


And here comes the makefile:

#
#   ROOT program's MAKEFILE.
#
#   Should be fairly portable. Tested on Sinclair QL
#     with C68 v4.12.
#
#   ROOT is the name of the compiled code, SFX the suffix
#     for source files.
#

ROOT = ram2_root
SFX = _c

$(ROOT): root$(SFX) makefile
    cc -QO root$(SFX) -o$(ROOT) -L$(LIB_DIR) -lm


   To compile the example program with C68 on the QL, copy
the source text to 'root_c' and the makefile to 'makefile'
where both files must be in the same directory. Now
redirect the default data device (that is the current
directory) to this directory, for example with DATA_USE.
Finally execute MAKE, eg. type 'ex make' from SuperBASIC.
The executable code (24k) will be placed in 'ram2_root'
unless you modify the MAKEFILE to your needs.

'ex root;"10"' ('root 10' from a shell) prints

    ROOT: Calculating...
    ROOT: The square root of 10.000000 is 3.162278.

   Try to find the root of 1e300 to see how the example can
slow down and to watch the numbers!

   All comments welcome. I claim no copyright over the ROOT
program.

Enjoy Coca Cola, errr... programming.
Franz Herrmann (Franz_Herrmann @ bn.maus.de)


PERMUATIONS
   BY HERB SCHAAF

[ Below is an interesting permutation program sent to me by
Herb Schaaf.  He did not include any article or explanation,
so I'll just present the program as is - ED]

100 REMark Permutation
110 REMark H L Schaaf
120 REMark February 28, 1994
130 REMark cleaned up from 'permutations' of January 27,
    1994
140 REMark to show permutations of n items taken r at a
    time
150 REMark where the order of the items is important
160 MODE 4
170 :
180 INPUT\ "Selection to be made from how many total items
    ?",n%
190 n$ = n%
200 INPUT '# of items at any one time to be selected from '
 &n$&' choices',r%
210 IF r% > n% THEN GO TO 180
220 facn = fac(n%)
230 facd = fac(n%-r%)
240 num_perms = facn/facd
250 PRINT 'There should be ';num_perms;' permutations'
260 :
270 REMark form an array and fill the first row
280 DIM a%(r%,n%)
290 FOR i = 1 TO n% : a%(1,i)  i : END FOR i
300 :
310 REMark make an array to hold permutations
320 DIM perm%(num_perms, r%)
330 PRINT\\,'touch [space bar] to continue'
340 PAUSE
350 perm_num = 0
360 FOR layer = 2 TO r%
370  make_lowerow a%,layer,1+n%-layer
380 END FOR layer
390 level% = r% : p% = 1 : DIM mark%(r%)
400 FOR i = 1 TO r% :mark%(i) = a%(i,1) : END FOR i
410 REPeat loop
420  mark%(level%) = a%(level%,1)
430  REPeat shifts
440   get_perm(p%)
450   p% = p% + 1
460   rot_left a%,level%,(n% + 1 - level%)
470   IF a%(level%,1)= mark%(level%) THEN
480     level% = level% - 1 : IF level% = 0 THEN EXIT loop
490     rot_left a%,level%,(n% + 1 - level%)
500     IF a%(level%,1) = mark%(level%) THEN GO TO 480
510       FOR layer = level% +1 TO r%
520         make_lowerow a%,layer,(1 + n% - layer)
530         mark%(layer) = a%(layer,1)
540       END FOR layer
550       level% = r%
560   END IF
570  END REPeat shifts
580 END REPeat loop
590 :
600 PRINT\ 'there should be ';p%-1;
610 PRINT ' permutations in array perm%(';
620 PRINT   num_perms%;',';r%;')'
630 PRINT 'touch [space bar] to see them'
640 PAUSE
650 FOR i = 1 TO p%-1
660 PRINT\' # ';i;' is ',
670 FOR j = 1 TO r%
680 PRINT perm%(i,j),
690 END FOR j
700 END FOR i
710 :
720 REMark function for factorial of number
730 DEFine FuNction fac(n%)
740 LOCal i
750 factorial = 1
760 FOR i =  n% TO 2 STEP -1
770 factorial = factorial * i
780 END FOR i
790 RETurn factorial
800 END DEFine
810 :
820 REMark a way to rotate-left
830 DEFine PROCedure rot_left(array%,row%,items%)
840 LOCal i,temp%
850 temp% = array%(row%,1)
860 FOR i = 1 TO items%-1
870 array%(row%,i) = array%(row%,i+1)
880 END FOR i
890 array%(row%,items%) = temp%
900 END DEFine rot_left
910 :
920 REMark if we want to watch, debug, etc.
930 DEFine PROCedure show_array(array%)
940 PRINT\
950 rows% = DIMN(array%,1)
960 cols% = DIMN(array%,2)
970 FOR i = 1 TO rows%
980 FOR j = 1 TO cols%
990 PRINT array%(i,j),
1000 END FOR j
1010 PRINT
1020 END FOR i
1030 END DEFine show_array
1040 :
1050 REMark a way to make a 'subrow' of remaining choices
1060 REMark array(row-1,col+1) is placed in array(row,col)
1070 DEFine PROCedure make_lowerow(array%, row%, limit%)
1080 LOCali
1090 FOR i = 1 TO limit%
1100 array%(row%,i) = array%(row%-1,i+1)
1110 END FOR i
1120 END DEFine make_lowerow
1130 :
1140 REMark  first column of a%() is a permutation
1150 DEFine PROCedure get_perm(p%)
1160 perm_num = perm_num + 1
1170 FOR i = 1 TO r% :perm%(p%,i) = a%(i,1) : END FOR i
1180 PRINT\'# ';perm_num;'  -> ',
1190 FOR i = 1 TO r% :PRINT a%(i,1);' '; : END FOR i
1200 END DEFine get_perm


PRIME NUMBER
   By Mike Fink

[ This article was sent in by Mike Fink, owner of Domino
Cubes, a Z88 Dealer.  Once Mike told me about his work, I
thought this would be a good article.  Plus, Mike has had
problems getting Academia to look at his work.  I plan to
additionally post this article to one of the math
newsgroups.

So, look over this article.  I hope you understand it better
than I (just a bit over my head).  Pass it to others that
might be interested.  I believe that it needs some peer
review to bolster it.

The article appears just as I recieved it.  Any typo's are
purely mine.  Anyone seriously interested in the article can
send me a note and I'll send a hardcopy of the original
article (just in case I mistyped something). - Ed ]


   I have spent 27 years of my life searching for the
answer to the question, is there a formula that will
generate only prime numbers or is that impossible?  Many
people since time began sought the answer and none have
found it; which is why I began the search.  In my warped
sense of my ego - at 17 years of age, I thought I could do
anything since I had never failed at anything yet at that
age.

   [ For the rest of this article the character E will
represent the Sigma (Sumation) math symbol.  Also, a '
placed before a character means that that character is
subscripted.  For example, V'1 means V sub 1.

   1. All primes (except 2, 3, and 5) end in 1, 3, 7 or 9.
   2. All primes exist in one of 24 families.
   3. The 24 families are the result of my research.
   4. The similarities in the 4 building blocks of DNA and
RNA plus the 24 chromosomes of man, to the 4 building
blocks of primes and its 24 families, has led me to
conclude that there exists a definiet relationship to the
secrets of primes and the secrets of double spiral helices.
   5. I am not knowdedgeable enough to enter the field of
bio-genetics, and maybe I am not smart enough anymore to
find the connection.  I am convinced that my conjecture as
to this relationship is of such importance, that someone in
the bio-genetic-math community should pursue this premise.

   The following article gives the framework of my results,
but first let me explain a few things;

   1. The level of mathmatics required to understand my
statments, requires ordinary high school stuff.
   2. The level of logic and reasoning is a little harder.
   3. All numbers divisible by 2, 3, and 5 have been
eliminated from the V numbers generated by EQ. 2, which
makes the sample to investigate much smaller.
   4. The composites are always made from 2 or more primes.
   5. Composites that are squares can only occur in V'a
numbers ending in 1 or 9.

   PREMISE: A formula (or formulae) which will allow a
number N to be investigated to determine if it is a prime -
is possible.

   ATTITUDE: If a formula is found that generates all primes
but contains a few non-primes that smell differently, and a
test to remove the smelly ones is an easy test, this would
and should satisfy the conditions for a viable solution.
What remains then is a definition for easy.

   1. All primes beyond 2, 3, and 5 have the units digits of
1, 2, 7, or 9.
   2. EQ. 2 generates all primes, plus a small group of
non-primes and 1 is considered prime for purposes of family
identifications, or maybe it is a prime.
   3. In EQ. 2, all primes have the factors or roots of
R'1=1 and R'2=N; for the non-primes R'1=7 or larger in the
form of R'1=V+90C (See EQ. 7 & 8).
   4. E'm signifies the summing of the digits in a number to
a single digit, this digit, for numbers generated by EQ. 2,
can only be 1, 4, 7, 2, 5 or 8 (6 choices).
   5. POSTULATE: E'm of N = (E'mR'1)(E'mR'2) = (E'mV'1)(E'mV'2).
   6. POSTULATE: All numbers generated by EQ. 2 fall into 24
families, ie: E'm has only 6 posibilities (1,4,7,2,5,8) and
the units digit of N only has 4 ways to happen (1,3,7,9)
creating (6x4) 24 families.
   7. The first 12 numbers generated by EQ. 3 and EQ. 4 (See
Table 1), yield "V" numbers; 12 V'a and 12 V'b.
   8. HYPOTHESIS: To find a formula to satisfy the premise
considering all potential primes at once is difficult, if
not impossible; but by breaking the potential primes into
the 24 families, order can be found within each family.
   9. AXIOM:
      A. All numbers generated by EQ. 2 are either prime or not.
      B. All non-primes generated by EQ. 2 have roots that
can be found by EQ.'s 16, 17, and 18 -- or EQ.'s 9 and 10.
      C. Therefore if B is true, all other number are prime.
   10. PROOF THAT B IS TRUE:
      A. Table 2 shows that all the conbinations of
(V'1)(V'2) that will satifsy postulate 5.
      B. For any N in a given "V" family, there are either
12 or 14 combinations of (V'1)(V'2) to be inserted into
EQ.'s 16, 17, and 18.
      C. If N is not prime, integer roots other than R'1=1
will appear: therefore B of 9 is true.

EQ.  1: N = V+90C  (See EQ. 5)
EQ.  2: N = 6n+-5 where n<>5K  1<=k<=infinity
EQ.  3: N'a = 6n-5  (See Table 1)
EQ.  4: N'b = 6n+5  (See Table 1)
EQ.  5: N'a = V'a+90C'a
        N'b = V'b+90C'b  (See EQ. 1)
EQ.  6: C = (N-V)/90     (See EQ. 1)
EQ.  7: N = R'1R'2  (R'1 and R'2 = Roots or Factors)
EQ.  8: N = (V'1 + 90C'1)(V'2 + 90C'2) = V+90C
EQ.  9: N'a = X^2 - 9Y^2
EQ. 10: N'b = 9X^2 - Y^2
EQ. 11: N'aN'a1 = N'a2
        N'bN'b1 = N'a3
        N'aN'b = N'b2
EQ. 12: X'a = (R'1 + R'2)/2 = 3(n'1+n'2)+-5
EQ. 13: X'b = (R'1 + R'2)/6 = (n'1 + n'2)
EQ. 14: Y'a = (R'2 - R'1)/6 = (n'2 - n'1)
EQ. 15: Y'b = (R'2 - R'1)/2 = 3(n'2 - n'1)+-5
EQ. 16: If C'1 = 0, (N-V'1V'2)/V'1 = 90C'2
EQ. 17: If C'2 = 0, (N-V'1V'2)/V'2 = 90C'1  (See EQ. 8)
EQ. 18: When C'1 or C'2 <>0;
          (N-V'1V'2-90V'2C'1)/(V'1+90C'1) = 90C'2
          (N-V'1V'2-90V'1C'2)/(V'2+90C'2) = 90C'1

        TABLE 1

         -----------------
         | n | V'a | V'b |
         |---|-----|-----|
         | 1 |  1  |  11 |
         | 2 |  7  |  17 |
         | 3 |  13 |  23 |
         | 4 |  19 |  29 |
         | 6 |  31 |  41 |
         | 7 |  37 |  47 |
         | 8 |  43 |  53 |
         | 9 |  49 |  59 |
         | 11|  61 |  71 |
         | 12|  67 |  77 |
         | 13|  73 |  83 |
         | 14|  79 |  89 |
         -----------------

TABLE 2       VALUES FOR V'2

  -------------------------------------------------------------------------
  | V'a    1    V'b | V'a    3    V'b | V'a    7    V'b | V'a    9    V'b |
  -------------------------------------------------------------------------
  | 1| 4| 7| 2| 5| 8| 1| 4| 7| 2| 5| 8| 1| 4| 7| 2| 5| 8| 1| 4| 7| 2| 5| 8| EmR'2
---------------------------------------------------------------------------------
01|91 31 61 11 41 71|73 13 43 83 23 53|37 67 07 47 77 17|19 49 79 29 59 89|
73|37 67 07 47 77 17|91 31 61 11 41 71|19 49 79 29 59 89|73 13 43 83 23 53|  1
37|73 13 43 83 23 53|19 49 79 29 59 89|91 31 61 11 41 71|37 67 07 47 77 17| EmR'1
19|19 49 79 29 59 89|37 67 07 47 77 17|73 13 43 83 23 53|91 31 61 11 41 71|
---------------------------------------------------------------------------------
31|61 91 31 41 71 11|43 73 13 23 53 83|07 37 67 77 17 47|79 19 49 59 89 29|
13|07 37 67 77 17 47|61 91 31 41 71 11|79 19 49 59 89 29|43 73 13 23 53 83|  4
67|43 73 13 23 53 83|79 19 49 59 89 29|61 91 31 41 71 11|07 37 67 77 17 47| EmR'1
49|79 19 49 59 89 29|07 37 67 77 17 47|43 73 13 23 53 83|61 91 31 41 71 11|
---------------------------------------------------------------------------------
61|31 61 91 71 11 41|13 43 73 53 83 23|67 07 37 17 47 77|49 79 19 89 29 59|
43|67 07 37 17 47 77|31 61 91 71 11 41|49 79 19 89 29 59|13 43 73 53 83 23|  7
07|13 43 73 53 83 23|49 79 19 89 29 59|31 61 91 71 11 41|67 07 37 17 47 77| EmR'1
79|49 79 19 89 29 59|67 07 37 17 47 77|13 43 73 53 83 23|31 61 91 71 11 41|
---------------------------------------------------------------------------------
11|41 11 71 91 61 31|23 83 53 73 43 13|77 47 17 37 07 67|59 29 89 19 79 49|
83|77 47 17 37 07 67|41 11 71 91 61 31|59 29 89 19 79 49|23 83 53 73 43 13|  2
47|23 83 53 73 43 13|59 29 89 19 79 49|41 11 71 91 61 31|77 47 17 37 07 67| EmR'1
29|59 29 89 19 79 49|77 47 17 37 07 67|23 83 53 73 43 13|41 11 71 91 61 31|
---------------------------------------------------------------------------------
41|11 71 41 31 91 61|83 53 23 13 73 43|47 17 77 67 37 07|29 89 59 49 19 79|
23|47 17 77 67 37 07|11 71 41 31 91 61|29 89 59 49 19 79|83 53 23 13 73 43|  5
77|83 53 23 13 73 43|29 89 59 49 19 79|11 71 41 31 91 61|47 17 77 67 37 07| EmR'1
59|29 89 59 49 19 79|47 17 77 67 37 07|83 53 23 13 73 43|11 71 41 31 91 61|
---------------------------------------------------------------------------------
71|71 41 11 61 31 91|53 23 83 43 13 73|17 77 47 07 67 37|89 59 29 79 49 19|
53|17 77 47 07 67 37|71 41 11 61 31 91|89 59 29 79 49 19|53 23 83 43 13 73|  8
17|53 23 83 43 13 73|89 59 29 79 49 19|71 41 11 61 31 91|17 77 47 07 67 37| EmR'1
89|89 59 29 79 49 19|17 77 47 07 67 37|53 23 83 43 13 73|71 41 11 61 31 91|
---------------------------------------------------------------------------------

**|14 14 14 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 14 14 14 12 12 12|
  -------------------------------------------------------------------------
**  Possible Pairs
    Left-most column contains V'1 numbers.

   Mike Fink's Remarkable Method of Finding Primes Without Dividing!!

   1. Choose any family; N=V+90C, say, N'b=V'b+90C, (EQ. 8)
   2. The largest composite number in that family is always
known.
   3. Choose N'be larger then N'b.
   4. Is N'be a prime?
   5. The biggest composite less than N'be is known, ie; N'b.
   6. The smallest composite bigger than N'b can easily be
generated; see example below.
   7. Every number in this family between these two
non-primes, is, buy definition, a prime.

   EXAMPLE:  N'b = 77 + 90C = 707 = 77+90(7)..Largest known
non-prime.

   Let N'be = 1067; C'e = 11.  Is 1067 a prime?
   All non-primes, in this family, have roots = R'1R'2 =
N'axN'bx = (V'ax+90C'ax)(V'bx+90C'bx)
   R'1 must be equal to or greater than 7; See Tables 1 or 2.

(V'ax+90C'x)(V'bx+90Cx) =   R'1  R'2   = N'bx
-------------------------------------------------

(91+90C'x) (77+90C'x)   =  (91)  (77)  = 7007
(07+90C'x) (11+90C'x)   =  (97)  (11)  = 1067 **
(13+90C'x) (89+90C'x)   =  (13)  (89)  = 1157
(19+90C'x) (23+90C'x)   =  (19) (113)  = 2147
(31+90C'x) (17+90C'x)   = (121)  (17)  = 2057
(37+90C'x) (41+90C'x)   =  (37)  (41)  = 1517
(43+90C'x) (29+90C'x)   =  (43)  (29)  = 1247
(49+90C'x) (53+90C'x)   =  (49)  (53)  = 2597
(61+90C'x) (47+90C'x)   =  (61)  (47)  = 2867
(67+90C'x) (71+90C'x)   =  (67)  (71)  = 4757
(73+90C'x) (59+90C'x)   =  (73)  (59)  = 4307
(79+90C'x) (83+90C'x)   =  (79)  (83)  = 6557

  ** = The smallest non-prime bigger than 707 and less than
or equal to 1067.  Therefore ALL family numbers between 707
and 1067 must be, and are PRIMES!

   797, 887, and 977 are primes!

   The numbers used above are from Table 2 and show the 12
possible V numbers that will satisfy Eq. 11 and postulate 5.
 The C'x numbers are chosen to be in the range of the
problem.

   It is now obvious that it is possible to deduce multiple
primes without dividing, for each and every family.  The
time and effort required is less than for any other known
method!  Some families have 14 combinatorial pairs Em, the
rest have 12.

[ This is a almost literal translation of the original Z88
program by Mike.  I've tested it with the example runs
provided by Mike - Ed ]

100 REMark Prime Numbers - Mike Fink
110 REMark This program ascertains the primality of any
120 REMark number less than a billion.
130 REMark (C) 1988 by Mike Fink with help from
140 REMark  Robert Fink
150 INPUT "  Enter Number ";n
160 dv = 0 : time = DATE
170 IF n = 2 OR n = 3 OR n = 5 THEN GO TO 360
180 IF n/2=INT(n/2) OR n/3=INT(n/3) OR n/5=INT(n/5) THEN GO TO 400
190 DIM x(24)
200 g = SQRT(n)
210  x(1)=7 : x(2)=11 : x(3)=13 : x(4)=17 : x(5)=19
220  x(6)=23 : x(7)=29 : x(8)=31 : x(9)=37 : x(10)=41
230  x(11)=43 : x(12)=47 : x(13)=49 : x(14)=53 : x(15)=59
240  x(16)=61 : x(17)=67 : x(18)=71 : x(19)=73 : x(20)=77
250  x(21)=79 : x(22)=83 : x(23)=89 : x(24)=91
260 c = 0
270  FOR y = 1 TO 24
280    v1 = x(y) + 90 * c
290    IF v1 > g THEN GO TO 360
300    v2 = n/v1
310    dv = dv + (24 * c) + y - 1
320    IF v2 = INT(v2) THEN PRINT " v1 = ";v1;"  v2 = ";v2 : RUN
330 NEXT y
340 c = c + 1
350 GO TO 270
360 PRINT " N = ";n;" is a prime."
370 PRINT " No. of Divisions = ";dv
380 PRINT " Time = ";DATE-time
390 RUN
400 PRINT "N = ";n;" is not a prime"
410 RUN

Example Output:

  N = 117  Is not prime.

  N = 119   V'1 = 7   V'2 = 17

  N = 1119 Is not prime.

  N = 11119 Is a prime!  No. of Divisions = 351

  N = 966666661 Is a prime!  No. of Divisions = 34,357,905
