Updated 2018-07-09 08:26:21 by pooryorick

New Ulam Spiral Browser is the installment in the Primal Screens series. A brief description of the browser is given here followed by the associated Tcl/Tk source files.

See Also  edit

Primal Screens
The first browser in this seriews.
Primal Screens— Part Two
The second.
Monster Prime Predicting Formula
A simple formula that predicts a large number of prime numbers.
Gerard Sookahet
Has contributed numerous visualizations related to prime numbers.
Ulam spiral
The famous spiral visualization of prime numbers.

Description  edit

The New Ulam Browser has two windows, a Control Window and a Canvas Window in which Ulam spirals are plotted. On startup the control window appears all by itself with the main control buttons at the top. To start, first choose between SQUARE or TRIANGULAR grids and then select one of the granularity buttons, Coarse Grid or Fine Grid . The corresponding Ulam spiral will then appear in the canvas window.

Figure 1 is a superposition of the two windows, with the control window in the foreground, top left, and part of the Coarse Triangular grid in the background. Normally, the two windows are separated, with the control panel off to the side of the plotting canvas. In Figure 1, the Coarse Triangular grid is tiled with small numbered squares. Prime Integers are in Bold and Navy Blue, non prime integers are in Gray. The three dark blue lines are the Principle Axes for this system. The listbox in the control panel shows the highlighted formula for the trajectory that is displayed. Primes on the trajectory are indicated by red squares with a bold white integer. Non Primes are white squares with red outlines and gray bold integers. The trajectory has three branches.

FIGURE 1 edit

There are two buttons below the main buttons in the control panel. The first is for labeling a trajectory and the other for recording details of the trajectory. In Figure 1, the trajectory formula Label appears in red with white bold text.

Below these two buttons is a blue Entry Window and a Clear Button to the side. Below that is a listbox containing prime predicting formulae. Once the granularity has been selected, a mouse click on any formula in the listbox causes the trajectory for that formula to be overlaid on the Grid. In the Square Grid representation, a formula trajectory has two branches. In the Triangular representation, a trajectory has three.

For the Fine Resolution Grid, primes are designated simply as small blue plus signs. For a given trajectory in the Fine grid, primes are designated by small colored squares and non primes are small circles outlined in the same color. On either grid, an existing trajectory can be removed by clicking a second time on its previously selected formula in the listbox.

In figure 1, the formula m * ( m + 1) / 2 - 5 was selected from the listbox and portions of the three branches of it's trajectory appear on the canvas.

The blue formula entry window above the listbox is used to enter formulae for new trajectories. First click in the blue entry window to enter a new formula, then type in the formula. The formula must be of the form 2 * m * m - m - 13, followed by a return. The lower case letter m represents an integer which is incremented along the trajectory and is the only variable the program recognizes. The new formula will be appended at the bottom of the formula listbox and it's trajectory will be plotted. The clear button must be pressed before another formula can be entered. Spaces have been added in this example for clarity and are not necessary for the calculation. The code for handling formulae is very simple and does not have the ability to handle entries such as .

FIGURE 2 edit

Figure 2 is another superposition of the control canvas and a portion of the plotting canvas, this time for the Fine Square Grid. In the plotting canvas, we now have a display of all primes that are less than 500K. The primes are indicated by the small Navy Blue plus signs. As mentioned in previous work, Primal Screens, the inner blue square represents the extent of the Coarse grid. The next outer square is the limit of all primes less than 100K and the last square confines all primes less than 300K.

The formula m * m - m + 493 was entered in the entry window and upon typing return, the formula was added at the bottom of the listbox. The formula’s trajectory and label were then displayed. Primes on the trajectory are indicated by small red squares, non primes are little circles outlined in red. The trajectory has two branches.

FIGURE 3 edit

Finally, Figure 3 is thrown in just to show an interesting discovery. In the Fine Triangular Grid we see two distinctly different formulae which appear to have the same trajectory. The two formulae are: m * (m + 1) / 2 + 257 which calculates 89 Primes out of 988 predictions. for a Potency of 0.090 and 2 * m * m + 3 * m + 257 which calculates 87 Primes out of 493 predictions for a Potency of 0.176. The second formula strides through the field of primes twice as quickly as explained in Monster Prime Predicting Formula and has two fewer primes than the first formula.

FIGURE 4 edit

06.18.18 #2 copy

Upon further investigation, I discovered that my first assumption was incorrect. After printing out the primes and their corresponding values of m, two distinctly different sets of prime numbers showed up. Figure 4 above, shows that the two trajectories are very similar, but different. Here we see the two formulae plotted over a portion of the triangular set for all primes less than 100K. Notice the red and blue squares along the vertical branch near the left edge. At this resolution, they and the corresponding non primes are actually separated side by side. So there are really two distinct trajectories.

Need for a mathematician edit

The browser has raised several questions that perhaps a mathematician might try to answer.

Geometry based questions: In both systems, some trajectory branches have bends or breaks in direction. In formulae such as m * m - m + C, bends occur farther out as C increases. Often the bends occur as a branch crosses a Principle Axis and line segments between bends often are not aligned with the prime rich directions. What explains this behavior?

In both the Square and Triangular systems, prime rich directions are either parallel, anti-parallel or perpendicular to the Principle Axes. Why does this happen?

Why do two distinctly different formulae predict almost the same trajectories (see figs 3 and 4 above)?

Why are there prime rich directions in the first place and not just some random display? Why are some branches empty of primes? Perhaps these are satisfying questions for some mathematician.

Dedication edit

This is the last of the Primal Screen episodes. It has been difficult documenting all of this, mainly because Discovery has been much more fun than documenting. I’ve worked on the project on and off for some 15 years now, and as my son tells me about music projects— they are never finished, just abandoned. So, the Primal Screen project is now officially abandoned. I dedicate this work first of all to the memory of Stanislaw Ulam, who being blessed with a dull meeting and a quadrille tablet discovered what we now call Ulam Prime Spirals.

Next, I dedicate the following Tcl/Tk code to anyone who would venture further into this arena. I believe there is much yet to be discovered here and so this is for those hardy souls. I no longer have the time or energy to continue.

Future Directions edit

Here are some areas where someone might do further work:

Simple

—Working with the browser could be a nice project for advanced High School or beginning College students. They could learn something about Tcl/Tk coding and learn something about prime numbers by systematically varying formulae and posing their own questions. A better selection of colors could be made for plotting trajectories.

—Modify the code to make Clockwise Spirals. What would those trajectories look like for the same formulae? Instead of starting at integer 1, make the first starting square be something like 19. How would this affect the trajectories, potencies?

—What happens if one were to advance the set of primes to Primes LT 1,000,000? It would take some modification of the sizes of symbols, squares and screen size. Would Euler’s formula still be impressive for Primes Less than 1,000,000? Would a given formula still have bends further out?

More difficult

—Refactoring the code and adding new features. Trying other Grids— Hexagonal or Octagonal. What sort of formulae would be needed? Hint: See **Sloane’s On-Line Encyclopedia of Integer Sequences** [oeis.org]

Much More difficult

Create a magnifying glass for the Fine screen. It would be guided by cursor movements and would reveal a region around the cursor with enlarged readable numbers for the squares below. It would make discovering the closeness of trajectories such as found in Figure 4 much easier. I think this would be a difficult feature to implement.

The code itself edit

The current code is a melding of two previous separate browsers, one for Square geometry, the other for Triangular. Procs which had similar responsibilities in the two versions were mangled so as to eliminate overhead. The last of the known bugs has finally been smashed, but most likely there are still some that are not yet known. One caveat is that the code was developed on a Mac system and I don’t know how well it will translate to a Windoze machine.

The code will not run by itself without the companion file named PrimesList which the code sources upon startup. It must be in the same directory as the source code. In the early stages of this work, it was decided to create this list of prime numbers which could be searched, rather than having to calculate primes all the time. This allowed for a great speed advantage.

Two procs are included in the code which contain various formulae for the Square and Triangular grids. After selecting the granularity, the appropriate formulae will be entered in the Formula Listbox from one of these procs. If however, one of the files sq_Formula_File.tcl or tri_Formula_File.tcl is in the same directory as the browser, then formulae from the appropriate file will be placed in the listbox.

Stats on number of primes and speed of operation edit

I would have preferred to report on the speed at which the browser sources the list of Primes, followed by the speed of plotting a grid, but haven’t been able to figure out how to do that. All in all, it is FDQ (Fairly Darned Quick).

There are 41538 Primes Less Than 500,000. This means that for the Fine grid, a list of 41538 prime numbers is first sourced in, and then 500,000 small squares are calculated with 41538 plus marks at the appropriate positions. All of this happens rather rapidly on an iMac 4K Retina computer. For a typical formula, m * (m + 1) / 2 + 157, in the Triangular System, 988 predictions are made and 202 Primes are found, all rather quickly.

UlamGrids.tcl  edit

#!/bin/sh
# \
exec wish "$0" ${1+"$@"}


#      Latest Version: June 19, 2018    
#
#      This is file UlamGrids.tcl
#    
#      Procs appear in alphabetic order
#
#      Keith W, Johnson
 

package require Tk

#
#   First some global variables common to both Square & Triangular systems
   set annotateIndex 0
   set biggestPrime 0
   set bkgndColor {}
   set btmlft {}
   set btmrt {}
   set canvasWindow {}
   set color {}
   set commentString {}
   set coordSystem {}
   set Dbl_Button {}
   set delta 20
   set entryStrng {}
   set fgndColor black
   set fgndColorDx 0
   set formCount 0
   set formInput {}
   set formulae {}
   set formulaName {}
   set formulasRead 0
   set formList {}
   set formNumberList {}
   set foundPrime 0
   set granularity {}
   set haveGranularity 0
   set ix 0
   set iy 0
   set labelButton 0
   set labelId {}
   set lastm 0
   set lastPrime 0
   set lastVertex {}
   set lb {}
   set nextOp "right"
   set nucX 0
   set nucY 0
   set numIterations 5
   set numPrimesCalcd 0
   set out {}
   set outLineColor lightblue1
   set outString {}
   set plusSize {}
   set potency 0
   set prevVertexNumber 1
   set primeColor white
# Determine screen width.
   set screenwd [winfo screenwidth .]
   set srcFileName {}
   set sqNum 1
   set SQ_selected 0
   set SQ_Formulas_Read 0
   set startingIndex $sqNum
   set tagName line
   set top {}
   set TR_selected 0
   set TR_Formulas_Read 0
   set twoDelta [expr {2*$delta}]
   set vertexNumber 1
   set vertexValues {}
   set xRet 0
   set yRet 0

   set runningIndex [expr {$startingIndex - 1}]

#  Thanks much to uniquename = Blaise Montandon for the following colors.  I've 
#  rearranged them so there is a contrast between sequential selections. Colors
#  are arranged into Background and Foreground colors.
  
set squareColors { {white  black}  \
          {"#FF0000" white} {"#6600FF" white} {"#FFCC00" black} \
          {"#0066FF" white} {"#FF6600" white} {"#00FF66" black} \
          {"#FF00CC" white} {"#00BBFF" black} {"#1144FF" white} \
          {"#CCDDBB" black} {"#BBFF00" black} {"#00BB00" black} \
          {"#66FF55" black} {"#CC00FF" white} {"#FF0077" white}
}
   
#
   set windowWidth [expr {int ( 0.5*$screenwd )}]
   set winht $windowWidth
   set x1 {}
   set x2 {}
   set y1 {}
   set y2 {}
   set xMin 10000
   set xMex -10000
   set yMin 10000
   set yMax -10000

#
#  PrimesList contains the list of Prime Numbers.

   set src_Name "PrimesList"
   if [file exists $src_Name] {
        source PrimesList
    } else {
        puts "\n\n\n   -----   Whoops!  You need the list of Primes first. "
        puts "   This list should appear in the file  PrimesList. \n"
        puts "   Use the file Primer.tcl to create this file. \n\n\n" 
        exit
    }


set biggestPrime [lindex $primes end]
puts "\n\n  ---  biggestPrime is $biggestPrime, number of primes is [llength $primes] "


##------------------------------------------
##  Proc array'reverse.
##
##  A Proc to invert an array.
##  Thanks to Example 8-4, "Practical Programming in Tcl and Tk"
##     Brent B. Welch, 3rd Edn.
##
##  Used in procs coarse doFormula and fine.
##-------------------------------------------
proc array'reverse { oldName newName } {

    upvar 1 $oldName old $newName new
    foreach {key value} [array get old] {set new($value) $key}

}


##------------------------------------------------------
##  Proc coarse
##
##  Create a Primal Screen using Coarse cells.
##    Works for Sq and Tri systems
##
#   If switching Geometries, the previous Ulam plot will
#   not vanish until a new resolution is chosen.
#
#   That is, if some plots were made in the Square Geometry
#   and then you switch to Triangular, the Coarse
#   or Fine buttons must then be selected before the Square 
#   Grid will disappear.
#
##------------------------------------------------------
proc coarse { } {

   global  btmlft btmrt canvasWindow coordSystem cX cY Dbl_Button delta formList       
   global  formulasRead granularity haveGranularity labelButton labelId numIterations       
   global  plusSize startingIndex top twoDelta V V2 vertexNumber windowWidth

   set Dbl_Button {}
   set delta 9
   set formList {}
   set formulasRead 0
   set twoDelta [expr {2*$delta}]
   set granularity "coarse"
   set haveGranularity 1
   set labelButton 0
   set labelId {}
   set numIterations 60
   #   set numIterations 30
   set plusSize 9
   set startingIndex 1
   set vertexNumber 1
   #   Following are based on a delta of 9
   set top 1770
   set btmrt 1891
   set btmlft 1830

   set cX [expr {int ($windowWidth / 2)}]
   set cY $cX

   reset

   puts "      COARSE GRID \n"

   createCanvas
   drawSquares
   $canvasWindow configure -scrollregion [$canvasWindow bbox all]

      if {[string compare $coordSystem "tri"] == 0} {
       array'reverse V V2
   }    

   drawCoords
   if {$formulasRead == 0} {
      readFormulae
   }

}


##----------------------------------------------------------------------------
##  Proc composeFormula
##
##  formInput is the formula that was entered in the entrybox in controlsSetup
##  This new formula will be added to the end of the formula listbox.
##
##----------------------------------------------------------------------------
proc composeFormula { } {

   global  formCount formInput formulae lb
 
   set formula {}
   append formula "$formInput"
   set formulaName "$formula"
   set newForm [list $formulaName ]
   lappend formulae $newForm

   set lstboxString [format "  %-s" $formulaName ]
   $lb insert end $lstboxString
   set idx [expr { $formCount -1}]
   $lb see $formCount

   formulaCalc $idx
   incr formCount

}


##----------------------------------------------------------------
##  Proc controlsSetup
##
##  A proc to create the Controls canvas.
##
##  Action Buttons and Formula Listbox are created in this canvas.
##
##----------------------------------------------------------------
proc controlsSetup { } {

   global  coordSystem entryStrng formInput formulasRead keepEntryStrng labelButton
   global  lastVertex lb nextOp out SQ_selected TR_selected vertexValues
 
#  dumpFile accumulates comments when Record button is selected.
#  
#   set dumpFile "~/Unix_TCL/Projects/Prime_Ribs/Phase_One/Newest/MergeDir/LATEST/NEW_FormulaDumpFile"

   set dumpFile "FormulaDumpFile"
   set out [open $dumpFile "a"]

   set entryStrng {}
   set labelFont [font create -family courier -weight bold -size 12]
   set xGeom1 1000
   set yGeom1 50
  
   wm geometry . +$xGeom1+$yGeom1
   wm attributes . -topmost 1
   focus .

#  Determine screen width and height.
   set screenwd [winfo screenwidth .]

#  Create the controls canvas.
   set fr1 [frame .fr1 -relief sunken -borderwidth 2 -height 30]
   pack $fr1 -fill x -side top  -in .

#  Create the Top Buttons frame.

   button $fr1.bSQ -text "SQUARE"  -width 10 -bg white -fg blue \
       -command {set coordSystem "sq"; set nextOp "right"; set $formulasRead 0; \
                puts "   SQUARE Coordinate System ";   }


   button $fr1.bTR -text "TRIANGULAR"  -width 11 -bg white -fg blue \
       -command {set coordSystem "tri"; set lastm 1; set lastVertex {}; \
                 set nextOp "tri_rt"; set prevVertexNumber 1; \
                 set vertexValues {}; set xRet 0; set yRet 0; set $formulasRead 0; \
                 puts "   TRIANGULAR Coordinate System ";   }


   button $fr1.bCG -text "Coarse Grid"  -width 10 -bg white -fg blue \
       -command "coarse"
   button $fr1.bFG -text "Fine Grid"  -width 11 -bg white -fg blue \
       -command "fine"
   button $fr1.bQ -text Quit -width 8 -bg white -fg blue \
       -command newExit

   pack $fr1.bSQ $fr1.bTR $fr1.bCG $fr1.bFG -side left
   pack $fr1.bQ -side right
  
   set fr1b [frame .fr1b -relief groove -borderwidth 2 -height 30]

   pack $fr1b -fill x -side top  -in .

#  Create the Label/Record Frame.   
   button $fr1b.label -text "Label"  -width 6 -bg white -fg blue \
       -command { set labelButton 1; drawAnnotationLabel }
   button $fr1b.record -text "Record"  -width 7 -bg white -fg blue \
       -command "makeCommentWindow"
   pack $fr1b.label -side left -padx 10 
   pack $fr1b.record -side right  -padx 10
   

   frame .f2 -relief sunken -borderwidth 2
   frame .f2.title
   pack .f2.title -side top

#  Create the Formula EntryBox and Clear Frame.  
#   
#  New formulae can be entered in this entry box.  Once entered and followed 
#  by Return, the new formula will be added at the end of the formula listbox and the
#  trajectory for this formula will be calculated and displayed.
#
#  Formulae must be entered like following:   m*m -38*m + 16

   frame .f2.a
   entry .f2.a.entryA -width 20 -relief ridge \
        -font $labelFont -bg "medium slate blue" -fg blue
   .f2.a.entryA insert end ""

   button .f2.a.clr -text Clear -width 8 -bg red -fg blue \
        -command {.f2.a.entryA delete 0 end; set formInput {}; set entryStrng {}}

   pack .f2.a.entryA .f2.a.clr -side left 
   pack .f2.a -side left
   pack .f2 -side top

#  Create the Listbox Frame Next.   
   frame .f3 -relief sunken  -borderwidth 2 -pady 10
   text  .f3.text -font "Courier 14" -wrap word \
      -yscrollcommand {.f3.text_y set} 
   scrollbar .f3.text_y -relief groove -command {.f3.text yview}

   set lb [listbox .f3.listbox -height 15 -width 28 \
      -yscrollcommand [list .f3.lb_y set] -selectmode extended \
      -xscrollcommand [list .f3.lb_x set] ]

   scrollbar .f3.lb_y -orient vertical -command [list $lb yview]
   scrollbar .f3.lb_x -orient horizontal -command [list $lb xview]
   grid $lb -sticky nw -padx 1 -row 2 -column 1
   grid .f3.lb_y -sticky nsw -padx 1 -row 2 -column 2
   grid .f3.lb_x -sticky ew -padx 1 -row 3 -column 1
   pack .f3 -side top 

   set fr4 [frame .fr4 -relief flat -borderwidth 2 -height 90]
   pack $fr4 -fill x -side bottom  -in .fr1

#  proc formulaCalc will be invoked here, because a formula was selected from the listbox---
   bind $lb <<ListboxSelect>> "formulaCalc -1"


#  After completing formula entry and typing Return, add formula to bottom of listbox.
   bind .f2.a.entryA <Return> {
           set formInput $entryStrng
           composeFormula
           set entryStrng {}
           break
   }

#  Text for Formula Entry handled here---
   bind .f2.a.entryA <KeyPress> {
      if {"%K" != "BackSpace"} {
              append entryStrng %A
      } else {
              set strng [string range $entryStrng 0 end-1]
              set entryStrng $strng
              set formInput $strng
      }
   }

   bind .fr1 <Enter> {
      focus .fr1
   }

   .f3.text tag configure "matched" -background yellow

   bind $fr1.bSQ <ButtonPress-1> {
      set SQ_selected 1;
   }

   bind $fr1.bTR <ButtonPress-1> {
      set TR_selected 1;
   }

}


##------------------------------------------
##  Proc createCanvas.
##
##  Create the Ulam Spiral canvas. Sq or Tri.
##
##------------------------------------------
proc createCanvas { } {

    global  canvasWindow coordSystem windowWidth

    set canvasWindow .w
    set borderwidth 2
    set hscroll $canvasWindow.hscroll
    set vscroll $canvasWindow.vscroll

    catch {destroy $canvasWindow}
    toplevel $canvasWindow
    if {[string compare $coordSystem "sq"] == 0} {
       wm title $canvasWindow "Square Ulam Canvas"
    } elseif {[string compare $coordSystem "tri"] == 0} {
       wm title $canvasWindow "Triangular Ulam Canvas"
    }
    wm geometry $canvasWindow +100+100
    focus $canvasWindow

    canvas .w.c -relief sunken -borderwidth $borderwidth \
          -width $windowWidth -height $windowWidth -bg "alice blue" \
          -xscrollcommand "$hscroll set" \
          -yscrollcommand "$vscroll set"
              
    scrollbar $hscroll -orient horiz -command ".w.c xview"
    scrollbar $vscroll               -command ".w.c yview"

    pack $hscroll -side bottom -fill x
    pack $vscroll -side right  -fill y
    pack .w.c  -side right  -fill both  -expand 1

    set canvasWindow .w.c
    update idletasks

}


##--------------------------------------------
##  Proc doFormula
##
##  Plot the trajectory of a chosen formula.
##  Works for Sq and Tri systems.
##
##--------------------------------------------
proc doFormula { newFormName tagName } {

    global  biggestPrime bkgndColor coordSystem cX cY fgndColor formulaName  
    global  foundPrime lastm lastPrime numPrimesCalcd out outString P 
    global  potency startingIndex vertexNumber  
 
#   Invert the P array, so the X Y coords of Prime P can be obtained
#   from the value of the Prime itself.  P array is created in isPrime.
    array'reverse P P2
    
    set calcdPrimesList {}
    set count 0
    set formula "expr { int($newFormName)}"
    set lastm 1
    set mPrimesList {}
    set num 0
    set numPredicted 0
    set numPrimesCalcd 0
    set prevVertexNumber 1

#   Create scripts for the two different coordSystems
    if {[string compare $coordSystem "tri"] == 0} {
#   Triangular coord system
       set startingIndex 1
       set vertexNumber 1
       set script1 {
         getTriCoords $num $tagName 1
       }
    } else {
#   Square coord system.
       set script1 {       
         set crds [getSqCoords $num 0]
         getSqCoords $num 1              
         set x [lindex $crds 0]
         set y [lindex $crds 1]
       }
    }

    for {set m 2} {$m < $lastPrime} {incr m} {
       set foundPrime 0
       set num [eval $formula]
       set ls [array get P2 $num]
       set indx1 [expr {[string first " " $ls] -1}]
       set indx2 [expr {[string first " " $ls] +1}]
       set coord [string range $ls $indx2 end]

       if { $num <= $lastPrime} {
           incr numPredicted
           incr count
       } else { break }

       if {![string match $coord ""]} {
#   prime coords found
          set foundPrime 1
          incr numPrimesCalcd
          set indx1 [expr {[string first "," $coord] -1}]
          set indx2 [expr {[string first "," $coord] +1}]
          set x [expr {[string range $coord 0 $indx1] + $cX}]
          set y [expr {[string range $coord $indx2 end] + $cY}]
#         Plot the Prime          
          plotSquare $num $x $y $fgndColor $bkgndColor $tagName 1
          lappend calcdPrimesList "$num"
          lappend mPrimesList "$m"
       } else {
#   non-prime coords found
#   a formula may predict some negative values for num.      
          if {($num > 1.0) && ($num <= $lastPrime)} {
             eval $script1
          }
       }
    }

        set numCoarse 0
        set numPrimesCalcd 0
        set calcdListLeng [llength $calcdPrimesList]
        for {set i 0} {$i <= $calcdListLeng } {incr i} {
#   last prime in coarse grid is 3593.
            if { [lindex $calcdPrimesList $i] < 3593} {
               incr numCoarse
            }
            if { [lindex $calcdPrimesList $i] < 500000} {
               incr numPrimesCalcd
            }
        }

#       After plotting all primes for this trajectory, do final stuff here.
        incr numCoarse -1
        incr numPrimesCalcd -1

        set potency  [format "%6.3f" [expr { $numPrimesCalcd / double($count) }] ]

        puts "\n  --  formula   $formulaName   calculates \
        $numPrimesCalcd Primes out of \
        $count predictions. \n      Potency is $potency \n"

        set firstPrime [lindex $calcdPrimesList 0]
        set lastcalcdPrime [lindex $calcdPrimesList end]
        set dt [clock format [clock seconds] ]

        set outString "\n $coordSystem -- $dt --, \n $formulaName | $biggestPrime |  \
                $firstPrime | $lastcalcdPrime | $numCoarse | $numPrimesCalcd | $numPredicted | \
        $potency, \n\n Calculated Primes:   m,prime \n "

#       Output values of m and corresponding Prime to dumpFile        
        for {set j 0} {$j <= $calcdListLeng} {incr j} {        
           append outString " [lindex $mPrimesList $j],"  "[lindex $calcdPrimesList $j] \n "
        }   
}


##---------------------------------------------------------------------------
##  proc drawAnnotationLabel
##
##  A proc to place an annotation label at some position on the canvas.
##  The label is the character string for the  plotted formula.
#
##  First, click the Lable button, then Double click the mouse at the point 
##  where the left edge of the label is to be drawn.
##  Somewhat Klunky!
##
##---------------------------------------------------------------------------
proc drawAnnotationLabel { } {
        
      global  annotateIndex bkgndColor canvasWindow Dbl_Button formList formulaName  
      global  fgndColor labelButton labelId

      set labelId {}
      set Dbl_Button 0
      if { [llength $formList] >= 1} {
         set annotateIndex [ lindex [lindex $formList end] 0 ]
      } else {
         set annotateIndex [ lindex [ lindex $formList 0] 0 ]
      }

      bind .w <Double-Button-1> {
#        To handle inadvertant Double-Button-1
         if { $Dbl_Button ==1} break

         set labelId {}
         set xLoc [ expr {[winfo pointerx $canvasWindow] - [winfo rootx $canvasWindow] } ]
         set yLoc [ expr {[winfo pointery $canvasWindow] - [winfo rooty $canvasWindow] } ]
         set path $canvasWindow.label$annotateIndex

         set labelName [ lindex [ lindex $formList end] 1 ]

         #  Colors for label are reversed
         set labelId [label $path -relief solid -bg $fgndColor -fg $bkgndColor \
         -text "$labelName"]

         place $labelId -x $xLoc -y $yLoc
         set Dbl_Button 1
         set labelButton 0
         set labelId {}
         update idletasks
      }

}


##------------------------------------------------------------------------
##  Proc drawBounds.
##
##  In the Fine representation, draw a triangle that approximates the
##  limits of the Triangular Format Coarse Screen.
##              or
##  Draw a square that approximates the limits of the Square Format Coarse
##  Screen.  plotLine is a proc used in the Square Format representation.
##
##  In both FINE representations, draw bounds for Primes less than 100K
##  and 300K, in the case that there are primes GT 300K.
##
##-------------------------------------------------------------------------
#
proc drawBounds { } {
        
      global  biggestPrime coordSystem tagName 

      set tagName coarse_bounds
      if {[string compare $coordSystem "sq"] == 0} {
#   Plot the boundary for the Coarse Square Format Screen.
         plotLine 1766 1891 blue2 
         plotLine 1891 1850 blue2
         plotLine 1850 1807 blue2
         plotLine 1807 1766 blue2

         if {$biggestPrime > 100000 } {
#   Bounds for Primes LT 100K
            plotLine 98911 99226 blue2
              plotLine 99226 99541 blue2
            plotLine 99541 99857 blue2
            plotLine 99857 98911 blue2
#   Bounds for Primes LT 300k            
              plotLine 298117 298663 blue2
            plotLine 298663 299210 blue2
            plotLine 299210 299757 blue2
             plotLine 299757 298117 blue2
         }

      } elseif {[string compare $coordSystem "tri"] == 0} {
#   Plot the boundary for the Coarse Triangular Format Screen.
#   Get x-y coords for the following integers.
         set top 1770
         set left 1830
         set right 1891

         TridrawLine $top $left blue2
         TridrawLine $left $right blue2
         TridrawLine $right $top blue2

         if {$biggestPrime > 100000 } {
#   Bounds for Primes LT 100K                 
            set top 98346
            set right 97903
            set left 97461       
            TridrawLine $top $left blue2
            TridrawLine $left $right blue2
            TridrawLine $right $top blue2
#   Bounds for Primes LT 500K        
             set top 488566
             set right 489555
             set left 490545
             TridrawLine $top $left blue2
             TridrawLine $left $right blue2
             TridrawLine $right $top blue2
#   Bounds for Primes LT 300K
             set top 298378
             set right 299151
             set left 299925
             TridrawLine $top $left blue2
             TridrawLine $left $right blue2
             TridrawLine $right $top blue2
          }   
       }

}


##--------------------------------------------------------------------
##  Proc drawCoords.
##
##  Draw Coordinate Axes through those cells which are the Squares of
##  Odd or Even numbers in the Square Format screen.
##         or
##  Overlay three blue Coordinate Axes on the Triangular Format Screen.
##  plotLine is a proc used in the Square Format representation.
##  TridrawLine is used in the Triangular Format representation.
#
##  These are the Principle Axes in each system.
## 
##---------------------------------------------------------------------
proc drawCoords { } {
        
      global  biggestPrime btmlft btmrt coordSystem granularity tagName top

      if {[string compare $coordSystem "sq"] == 0} {
#  Square Coord System
#  Plot a line through the Even and Odd squares.
         set tagName odd_even
         if {[string compare $granularity "fine"] == 0} {
            if {$biggestPrime < 100000 } {
               plotLine 4 99857 blue2
               plotLine 1 99226 blue2
            } elseif {$biggestPrime > 100000 } {
               plotLine 4 499849 blue2
               plotLine 1 498436 blue2
            }   
         } elseif {[string compare $granularity "coarse"] == 0} {
            plotLine 4 14400 blue2
               plotLine 1 14161 blue2 
         }
      } elseif {[string compare $coordSystem "tri"] == 0} {

#  Triangular Coord System 
#  Draw Axis 1  TO  TOP  
        TridrawLine 15 $top blue2
        
#  Draw Axis 2  TO BTM RIGHT    
        TridrawLine 10 $btmrt blue2        

#  Draw Axis 3  TO BTM LEFT
        TridrawLine 6 $btmlft blue2      
      }

}


##------------------------------------------------------------
##  Proc drawSquares.
##
##  Plot a square cell at the proper location for each integer.
##  For Coarse Screen, label each cell with integer.  Indicate
##  Prime numbers with colored text. 
## 
##  For the square that completes a triangle in the Triangular 
##  Format, store that integer in array V, which will have
##  indices x and y.
##
##  Thus:
##  -- Vertex V(9,-18) contains the integer 3 
##  -- Vertex V(-18,0) contains the integer 6 
##  -- Vertex V(27,18) contains the integer 10 
##  -- Vertex V(9,-54) contains the integer 15 
##  -- Vertex V(-45,18) contains the integer 21 
##  -- Vertex V(54,36) contains the integer 28 
##  -- Vertex V(9,-90) contains the integer 36 
##  -- Vertex V(-72,36) contains the integer 45 
##  -- Vertex V(81,54) contains the integer 55 
##
##------------------------------------------------------------
proc drawSquares { } {
        
   global  color coordSystem cX cY delta lastVertex nucX nucY numIterations
   global  runningIndex startingIndex V vertexValues xMin xMax yMin yMax out

#  Place the initial square cell here.
   square $cX $cY
   set runningIndex [expr {$startingIndex + 1}]
   set nucX $cX
   set nucY $cY

   if {[string compare $coordSystem "tri"] == 0} {
#  Triangular system here.
#    Use following puts statement to print out Vertex numbers as shown above.
#         puts "  For delta = $delta, \n"
      array unset V
      for {set i 1} {$i <= $numIterations} {incr i} {    
         Tri_iterate $i
         set VertexNum [expr {$runningIndex - 1}]
         lappend vertexValues $VertexNum
         set Xindex [expr {$nucX -$cX}]
         set Yindex [expr {$nucY -$cY}]
#   vertex coordinates are xindex and yindex.
         set V($Xindex,$Yindex) $VertexNum

#   Use following puts statement to print out Vertex Numbers as shown above.
#         puts  "  Vertex V($Xindex,$Yindex) contains the integer $VertexNum"
#         puts $out [expr {$VertexNum + 1}]
         set lastVertex $VertexNum
      }
   } else {
#   Square System here
         array unset P
         set color white
#   Wrap inverted "L" or "L" shaped patterns around the initial cell.
         for {set i 2} {$i <= $numIterations} {incr i} {
            Sq_iterate $i
         }
   }

   set xMin [expr {$xMin - $delta}]
   set yMin [expr {$yMin - $delta}]
   set xMax [expr {$xMax + $delta}]
   set yMax [expr {$yMax + $delta}]

}


##------------------------------------------------------
##  Proc fine
##
##  Create a Primal Screen using Fine cells.
##  Works for both Square and Triangular Format systems.
#
#   If switching Geometries, the previous Ulam plot will
#   not vanish until a new resolution is chosen, Coarse or
#   Fine.
#
#   That is, if some plots were made in the Square System
#   and then you switch to Triangular, the Coarse
#   or Fine buttons must be selected before the Square 
#   Grid will disappear.
##
##------------------------------------------------------
proc fine { } {
        
   global  biggestPrime btmlft btmrt canvasWindow coordSystem cX cY Dbl_Button 
   global  delta formulasRead granularity haveGranularity labelButton labelId    
   global  numIterations numPrimes plusSize primes startingIndex tagName top 
   global  twoDelta V V2 vertexNumber windowWidth

   set Dbl_Button {}
   set granularity "fine"
   set haveGranularity 1
   set labelButton 0
   set labelId {}
   set startingIndex 1
   set vertexNumber 1
   set formulasRead 0

#  For primes less than 100,000
   if {$biggestPrime > 400000} {    
      set delta .6
      set plusSize 6
   } elseif {$biggestPrime > 100000} {    
      set delta .7
      set plusSize 7

   } elseif {$biggestPrime > 30000} {
#      set delta 1
      set delta 1.3
      set plusSize 9
   } else {
#  For primes less than 30,000
      set delta 2   
      set plusSize 9
   }
   set twoDelta [expr {2*$delta}]

   puts "\n  This is fine, delta is $delta \n"

#  Integers at axis extremes for various sized prime fields.
   if {$biggestPrime < 100000 } {
      set top 98346
      set btmrt 97903
      set btmlft 97461      
   } elseif {$biggestPrime < 300000 } {
      set top 298378
      set btmrt 299151
      set btmlft 299925
   } else {
      set top 488566
      set btmrt 489555
      set btmlft 490545
   }

   set numIterations [expr {int (sqrt ($biggestPrime) )}]
   if {[string compare $coordSystem "tri"] == 0} {
      set numIterations [expr {int (1.4 * $numIterations)}]
   }

   set cX [expr {int ($windowWidth / 2)}]
   set cY $cX

   reset
   
   puts "      FINE GRID \n"

   createCanvas
   drawSquares
   $canvasWindow configure -scrollregion [$canvasWindow bbox all]

   if {[string compare $tagName "refLines"] == 0} {
   } else {
      $canvasWindow delete coarse_bounds
   }

   if {[string compare $coordSystem "tri"] == 0} {
       array'reverse V V2
   }

   drawCoords
   drawBounds
   set tagName refLines
   set numPrimes [llength $primes]
   if {$formulasRead == 0} {
      readFormulae
   }

}


##--------------------------------------------------------------
##  Proc formulaCalc.
##
##  When a Prime Predicting formula is entered in the entry box, 
##  or selected from the formula listbox, this proc is invoked to  
##  calculate the formula's trajectory.   If iCompose > 0, then the 
##  formula has been entered in the entrybox and does not come from 
##  the formula listbox. 
##
##---------------------------------------------------------------
proc formulaCalc { iCompose  } {
        
     global  annotateIndex bkgndColor canvasWindow fgndColor formList formNumberList
     global  formulae formulaName haveGranularity lb prevVertexNumber tagName
     global  startingIndex vertexNumber  

     set vertexNumber 1
     set prevVertexNumber 1

#  Whoops,  Must first specify granularity.
     if {$haveGranularity < 1} {
        puts "\n\n\n   -----   You must specify a granularity first." 
        puts "   -----   Click on Coarse Grid or Fine Grid before selecting a formula.  \n\n"
        return
     }

     if {$iCompose > 0} {
        set idx $iCompose
     } else {        
        set idx [$lb curselection]
     }

#    formString is used to make tags for individual trajectories so they can be deleted
#    sometime in the future.
     set formString "Formula"

#    formList contains 4 elements, the index of the formula in the listbox, followed by
#    the formulaName and then the foreground color and the background color.
#    The colors are not necessarily linked with the individual formulas,
#    but appear on a first come basis and are determined by proc set_Colors.
 
     
     set srchPtrn [get_formNumber $idx $formList]
#    Following is to handle the case where a previously selected formula is now to be
#    inactivated in the formula listbox and the trajectory removed from the canvas.
     if {[lindex $srchPtrn 0] > -1} {
       set annotateIndex $idx
       set tagName [append formString $idx]
       $canvasWindow delete $tagName

       set this "$canvasWindow.label$annotateIndex"
       destroy $this
       set annotateIndex 0
      
       $lb selection clear $idx
       repaint_formEntries $idx
       listBoxRemove formList $srchPtrn
       set tagName {}
       set formNumberList [lsearch -all -inline -not -exact $formNumberList $idx]
       return
     }

#    Proceed with formula calculation

     lappend formNumberList $idx
     set_Colors
     set realFormNumber $idx
     set formulaString [lindex $formulae $realFormNumber]
     set formulaName [lindex $formulaString  0]
     set tagName [append formString $realFormNumber]
     lappend formList [list $idx $formulaName $fgndColor $bkgndColor]

     $lb selection clear $idx
     $lb itemconfigure $idx -foreground $bkgndColor
     $lb itemconfigure $idx -background $fgndColor
     update idletasks
     set newFormName [search_formInputString $formulaName]
     doFormula $newFormName $tagName

}


##---------------------------------------------------------
##  Proc getSqCoords -- For Square Geometry
##
##  A proc to calculate the x y coordinates for the square 
##  containing the integer num.  If doPlot == 1, plot a 
##  small square at that location.  This proc plots Prime
##  and nonPrime numbers.  The x,y coords are returned.
##---------------------------------------------------------
proc getSqCoords {num doPlot} {
        
    global  bkgndColor cX cY fgndColor tagName twoDelta

    set srt [expr {int (sqrt ($num) )}]
    set diff [expr {$num - $srt * $srt}]

    if {[expr {fmod ($srt,2)}] > 0.0} {
       set xsq_location [expr { $cX + ($srt/2) * $twoDelta}]
       set ysq_location [expr { $cY + ($srt/2) * $twoDelta}]
       if { $diff == 0} {
            set x $xsq_location
           set y $ysq_location
       } elseif { $diff <= [expr { $srt + 1 }] } {
          set x [expr {$xsq_location + $twoDelta}]
          set y [expr {$ysq_location - $twoDelta * ($diff -1)}] 
       } else {
          set x [expr {$xsq_location - $twoDelta * ($diff - $srt - 2)}]
          set y [expr {$ysq_location - $twoDelta * $srt }] 
       }
    } else {
       set xsq_location [expr { $cX - ($srt/2 - 1) * $twoDelta}]
       set ysq_location [expr { $cY - ($srt/2) * $twoDelta}]
       if { $diff == 0} {
          set x $xsq_location
          set y $ysq_location
       } elseif { $diff <= [expr { $srt + 1 }] } {
          set x [expr {$xsq_location - $twoDelta}]
          set y [expr {$ysq_location + $twoDelta * ($diff -1)}] 
       } else {
          set x [expr {$xsq_location + $twoDelta * ($diff - $srt - 2)}]
          set y [expr {$ysq_location + $twoDelta * $srt }] 
       }
    }
    
    plotSquare $num $x $y $fgndColor $bkgndColor $tagName $doPlot

    if { $doPlot == 1 } {
       plotSquare $num $x $y $fgndColor $bkgndColor $tagName $doPlot
    } elseif {$doPlot == 2} {
       plotSquare $num $x $y $fgndColor $bkgndColor $tagName $doPlot
    }

    return [list $x $y]

}


##-----------------------------------------------------------------
##  Proc getTriCoords  -- For Triangular Geometry
##
##  A proc to calculate the x y coordinates in the Tri System for
##  the square containing the integer num.  The scheme is based on  
##  the coordinates for the triangular vertices which are stored in
##  array V.  If doPlot == 1, also plot a small square or circle at 
##  that location. This proc handles prime and nonPrime numbers.
##  The x,y coords for the square are returned.

#  The V2 array is the inversion of the V array and looks like:
#  -- The Vertex V2(3) is located at 9,-18 
#  -- The Vertex V2(6) is located at -18,0 
#  -- The Vertex V2(10) is located at 27,18 
#  -- The Vertex V2(15) is located at 9,-54 
#  -- The Vertex V2(21) is located at -45,18 
#  -- The Vertex V2(28) is located at 54,36 
#  -- The Vertex V2(36) is located at 9,-90 
#  -- The Vertex V2(45) is located at -72,36 
#     The series 3 6 10 15 21 28 36 etc.  are generated by the
#     Formula   m * (m+1) / 2.  Except for the integer 3,
#     this is the fundamental set of NON primes in the Tri System
#     and these constitute the Principal Axes in the Tri System.
#
#  The V array is created in the proc drawSquares.
#  The  proc tries to locate the two vertices that bound num.
#  It then finds the x and y coordinates of num based on the
#  coordinates of a vertex.
##  
##-------------------------------------------------------------
proc getTriCoords {num tagName doPlot} {
        
    global  bkgndColor delta fgndColor lastm lastPrime lastVertex  
    global  prevVertexNumber twoDelta V2 vertexNumber xRet yRet

#   vertexNumber keeps track of which Triangular Axis we are dealing with.    
    set vertexNumber $prevVertexNumber

    for {set m $lastm} {$m < $lastPrime} {incr m} {
        set vtxnum1 [expr {($m + 1)  * ($m + 2) / 2}]
        set strng1 [array get V2 $vtxnum1]
        set indx1 [expr {[string first " " $strng1] -1}]
        set value [string range $strng1 0 $indx1]

        if { fmod($vertexNumber,4) == 0} {
                 set vertexNumber 1
                 set prevVertexNumber 1
        }
#        puts "\n ---  vtxnum1 is $vtxnum1,  lastVertex is $lastVertex --- \n"
        if {$vtxnum1 > $lastVertex} { break }
        
        if {$value >= $num} {
#   Find value of first Vertex greater than num.
           incr indx1
           set key [expr {[string range $strng1 $indx1 end] }]

#   proc getVertex calculates xRet and yRet.
           getVertex $key  
           set Diff [expr {$value - $num}]  
           if {$vertexNumber == 1} {
              set x [expr { $xRet + $Diff * $delta}]
              set y [expr { $yRet + $Diff * $twoDelta}]
           } elseif {$vertexNumber == 2} {
              set x [expr { $xRet + $Diff * $delta}]
              set y [expr { $yRet - $Diff * $twoDelta}]
           } elseif {$vertexNumber == 3} {
              set x [expr { $xRet - $Diff * $twoDelta}]
              set y $yRet
           }
           if {$doPlot == 1} {
              plotSquare $num $x $y $fgndColor $bkgndColor $tagName 1
           } elseif {$doPlot == 2} {
              plotSquare $num $x $y white red $tagName 2
           }
           set lastm $m
           return [list $x $y]
        }
        incr vertexNumber
        incr prevVertexNumber
    }

}


##----------------------------------------------------------------
##  Proc getVertex 
##
##  A proc to extract the x and y Vertex Coordinates from key.
##     Called from getTriCoords.
##     Key looks like:    9,-54    for the Coarse Triangular Grid.
##     Depending on delta, the integer at this location is 28.  
##     See documentation in drawSquares.
##----------------------------------------------------------------
proc getVertex { key } {
        
    global  cX cY xRet yRet

    set strng1 $key
    set indx1 [expr {[string first " " $strng1] +1}]
    set indx2 [expr {[string first "," $strng1] -1}]
    set indx3 [expr {[string first "," $strng1] +1}]

    set xRet [expr {[string range $strng1 0 $indx2] + $cX}]
    set yRet [expr {[string range $strng1 $indx3 end] + $cY}]

}


##---------------------------------------------------
##  Proc get_formNumber
##
##  Extract the formula number from the formula list.
##
##---------------------------------------------------
proc get_formNumber { index this_formList } {

#   For description of this_formList see proc formulaCalc.        
#   This proc will return the index, foreground and background colors of the chosen 
#   formula which will be deleted from the active formulae in the formula listbox.

     foreach lst $this_formList {
        if {[lindex $lst 0] == $index} {
           return $lst
        }
     }
     return -1

}


##----------------------------------------------
##  Proc isPrime.
##
##  Determine if runningIndex is a Prime Number.
##  If so, add this Prime to array P.

#  The P array looks like this for the Coarse Square Format system:
#  -- The Prime Number 2 is located at 18,0
#  -- The Prime Number 3 is located at 18,-18
#  -- The Prime Number 5 is located at -18,-18
#  -- The Prime Number 7 is located at -18,18
#  -- The Prime Number 11 is located at 36,0
#  -- The Prime Number 13 is located at 36,-36
#  -- The Prime Number 17 is located at -36,-36
#  -- The Prime Number 19 is located at -36,0
#  -- The Prime Number 23 is located at 0,36
#  -- The Prime Number 29 is located at 54,-18
#  -- The Prime Number 31 is located at 54,-54
#  -- The Prime Number 37 is located at -54,-54
#  -- The Prime Number 41 is located at -54,18
#  

#  The P array looks like this for the Coarse Triangular Format system:
#  -- The Prime Number 2 is located at 18,0
#  -- The Prime Number 3 is located at 9,-18
#  -- The Prime Number 5 iis located at -9,-18
#  -- The Prime Number 7 is located at -27,18
#  -- The Prime Number 11 is located at 45,18
#  -- The Prime Number 13 is located at 27,-18
#  -- The Prime Number 17 is located at -9,-54
#  -- The Prime Number 19 is located at -27,-18
#  -- The Prime Number 23 is located at -36,36
#  -- The Prime Number 29 is located at 72,36
#  -- The Prime Number 31 is located at 54,0
#  -- The Prime Number 37 is located at 0,-108
#  -- The Prime Number 41 is located at -36,-36
##
##----------------------------------------------
proc isPrime { X Y } {
        
     global  color cX cY foundPrime lastPrime P primeColor   
     global  primeIndex primes runningIndex
 
     set foundPrime 0
     set color white
     if {[lindex $primes $primeIndex] == $runningIndex} {
        set color $primeColor
        set foundPrime 1
        set lastPrime $runningIndex
        set Xindex [expr {$X -$cX}]
        set Yindex [expr {$Y -$cY}]
#   Array P's index will be the X and Y coords of the found Prime number.
        set P($Xindex,$Yindex) $lastPrime
        incr primeIndex
     }
     incr runningIndex

}


##-------------------------------------------------
##  Proc listBoxRemove.
##
##  Unselect a previously selected listbox formula.
##
##-------------------------------------------------
proc listBoxRemove { listVariable value } {

    global  formulaName labelButton labelId

    upvar 1 $listVariable var
    set indx [lsearch -exact $var $value]
    set var [lreplace $var $indx $indx]

    destroy $labelId
    set labelButton 0
    set formulaName {}

}


##-----------------------------------------------------------------
##  Proc makeCommentWindow
##
##  Puts up a small window in which you can write a comment.
##  Write outString and comment to out
##
##-----------------------------------------------------------------
proc makeCommentWindow { } {
        
    global  commentString out outString

    set commentWindow .cmnt
    set borderwidth 2
 
    catch {destroy $commentWindow}
    toplevel $commentWindow
    wm title $commentWindow "Comment Window"
    wm geometry $commentWindow +400+300
    focus $commentWindow

    label $commentWindow.l -text "Type Comment Here: "
    entry $commentWindow.e -width 50 -relief ridge \
        -font "Courier 14" -bg "alice blue" -fg "blue"
    $commentWindow.e insert end " "
    pack $commentWindow.l $commentWindow.e  -side left  -fill both  -expand 1
    focus $commentWindow

    bind $commentWindow.e <Return> {
       set commentString [.cmnt.e get]
       puts $out "$outString "
       puts $out "$commentString \n"
       update idletasks
       destroy .cmnt
    }

}


##-----------------------------------
##  Proc newExit.
##
##  Before exiting, close file 'out'.
##
##-----------------------------------
proc newExit { } {
        
    global  out 

    close $out
    exit

}


##--------------------------------------------------------------------
##  Proc plotLine.
##
##  Plot a line connecting the two integers, start and end with color.
##--------------------------------------------------------------------
proc plotLine {start end color} {
        
    global  canvasWindow tagName

    set coords {}
    set crds [getSqCoords $start 0]
    set x1 [lindex $crds 0]
    set y1 [lindex $crds 1]
    set crds [getSqCoords $end 0]
    set x2 [lindex $crds 0]
    set y2 [lindex $crds 1]
    lappend coords [list $x1 $y1 $x2 $y2]
    eval {$canvasWindow create line} $coords \
         {-tag $tagName  -width 2 -fill $color}

}


##------------------------------------------------
##  Proc plotSquare.
##
##  Plot a square at x,y.  For Coarse Granularity,
##  emboss square with the integer num.  For Fine
##  plot a small plus if integer is prime, else plot 
##  a small circle if nonPrime.
##
##------------------------------------------------
proc plotSquare { num x y fgndColor bkgndColor tag doPlot } {
        
    global  canvasWindow foundPrime granularity plusSize

#   Fine case.
    if {[string compare $granularity "fine"] == 0} {
         if {$foundPrime == 1} {
            if {$doPlot ==1} {
               sm_sq $x $y 2.4 $fgndColor $fgndColor $tag 1
            }               
         } else {
                 sm_sq $x $y 1.4 white $fgndColor $tag 2
         } 
          
     } else {

#   Coarse case.
         if {$foundPrime == 1} { 
            if {$doPlot ==1} {
                  sm_sq $x $y 8 $fgndColor $fgndColor $tag 1
                 $canvasWindow create text $x $y -text $num -fill $bkgndColor \
               -font "Times $plusSize bold" -tag $tag
             } elseif {$doPlot ==2} {
               sm_sq $x $y 9 white $fgndColor $tag 2
                 $canvasWindow create text $x $y -text $num -fill $bkgndColor \ 
               -font "Times $plusSize bold" -tag $tag
             }
          } else {
               if {$doPlot ==1} {
               sm_sq $x $y 8 white $fgndColor $tag 1
                 $canvasWindow create text $x $y -text $num -fill slategray3 \
               -font "Times $plusSize bold" -tag $tag
              } elseif {$doPlot ==2} {
                sm_sq $x $y 8 white $fgndColor $tag 2
                $canvasWindow create text $x $y -text $num -fill slategray3 \
                -font "Times $plusSize bold" -tag $tag
              }                
          }  
    }
 
}


##--------------------------------------------------------------
##  Proc readFormulae.
##
##    Read in the list of Formulae from the Formula files.
##    There are separate files for Square and Triangular formats.
##    For Sq system, the formula file is sq_Formula_File.tcl
##    For Tri system, the formula file is tri_Formula_File.tcl
##
##---------------------------------------------------------------
proc readFormulae { } {

    global  coordSystem formCount formulae formulasRead
    global  lb srcFileName SQ_selected SQ_Formulas_Read 
    global  TR_selected TR_Formulas_Read

    set srcFileName {}

#  Handle details for case where one Grid system was first selected and then later the
#  other one is selected.
                
#  Selecting Sq Grid after Tri Grid had been viewed.
    if {[string compare $coordSystem "sq"] == 0} {
       if {$TR_selected == 1} {
           set TR_selected 0
           set formulasRead 0
           set formulae {}
           $lb selection clear 0 end
       }
#  Selecting Tri Grid after Sq Grid had been viewed.
    } elseif {[string compare $coordSystem "tri"] == 0} {
       if {$SQ_selected == 1} {
          set SQ_selected 0
          set formulasRead 0
          set formulae {}
          $lb selection clear 0 end           
       }
    }

    if {[string compare $coordSystem "tri"] == 0} {
       set srcFileName "tri_Formula_File.tcl"
       if [file exists $srcFileName] {
          source $srcFileName
       } else {
          if {$TR_Formulas_Read == 0} {
             tri_GridFormulae
          }
       }
    } else {
       set srcFileName "sq_Formula_File.tcl"
       if [file exists $srcFileName] {
          source $srcFileName
       } else {
          if {$SQ_Formulas_Read == 0} {
             sq_GridFormulae
          }
       }
    }

    set formCount 1
    $lb delete 0 end
    foreach form $formulae {
       set formulaName [lindex $form 0]
       set lstboxString [format "  %-s" $formulaName ]
       $lb insert end $lstboxString
       incr formCount
    }
    $lb see 0
    set formulasRead 1

}


##----------------------------------------------------------------
##  Proc repaint_formEntries
##
##  Remove the listbox background color of a formula that has been
##  unselected from the formula listbox.
##
##----------------------------------------------------------------
proc repaint_formEntries { indx } {
        
     global  bkgndColor fgndColor lb

     set fgndColor black
     set bkgndColor white
     $lb itemconfigure $indx -foreground $fgndColor
     $lb itemconfigure $indx -background $bkgndColor

}


##----------------------------------------------------
##  Proc reset
##
##  Reset some global variables to initial conditions. 
##
##----------------------------------------------------
proc reset { } {
        
   global  color coordSystem cX cY delta fgndColorDx formList 
   global  formNumberList foundPrime lastm lastPrime lb nextOp nucX nucY
   global  prevVertexNumber primeColor primeIndex P runningIndex sqNum startingIndex
   global  tagName vertexNumber windowWidth xMin xMax yMin yMax

   set color {}
   set cX [expr {int ($windowWidth / 2)}]
   set cY $cX
   set fgndColorDx 0
   set formList {}
   set formNumberList {}
   set foundPrime 0
   set lastm 1
   set lastPrime {}
   
   if {[string compare $coordSystem "tri"] == 0} {
      set nextOp "tri_rt"
      set prevVertexNumber 1
      set vertexNumber 1
   } else {
      set nextOp "right"
   }

   set nucX {}
   set nucY {}
   array unset P
   set primeColor white
   set primeIndex 0
   set sqNum 1
   set startingIndex $sqNum
   set runningIndex [expr {$startingIndex - 1}]
   set tagName line
   set twoDelta [expr {2*$delta}]
   set xMin 10000
   set xMax -10000
   set yMin 10000
   set yMax -10000
   foreach lst $formNumberList {
      $lb itemconfigure $lst -background white
      $lb itemconfigure $lst -foreground black
      $lb selection clear $lst
   }
   set indx [$lb curselection]
   if {$indx > 0} {
      $lb selection clear $indx
   }

}


##---------------------------------------------------------------
##   Proc search_formInputString.
##
##   This proc converts all m's in strng to $m's.  $m is the
##   variable that gets incremented in proc doFormula.  m is for
##   printing, $m is for calculating.  Gloriously Klunky, no?
##
##---------------------------------------------------------------
proc search_formInputString { strng } {

    set mcharreplace \$m
    set modString ""
    set inStringLeng [string length $strng]
    set strngPosn 0
    for {set i 0} {$i <= $inStringLeng } {incr i} {
        set formChar [string range $strng $i $i] 
        if {$formChar == "m"} {
           append modString "$mcharreplace"
        } else {
           append modString $formChar
        }
    }
    return $modString

}


##-------------------------------------------------------------------
##   Proc set_Colors.
##
##   Choose foreground and background colors from array squareColors.
##
##-------------------------------------------------------------------
proc set_Colors { } {
        
     global  bkgndColor fgndColor fgndColorDx squareColors
   
     if {$fgndColorDx < 16} { 
        incr fgndColorDx    
     } else {
        set fgndColorDx 0
     }
     set fgndColor [lindex [lindex $squareColors $fgndColorDx] 0]
     set bkgndColor [lindex [lindex $squareColors $fgndColorDx] 1]

}


##-----------------------------------------------------------------------
##   Proc sm_sq.
##
##   Draw a small square cell, centered on x and y with side length
##   (2 * delt).  Color square with color thisColor.  Tag square
##   with tagName. Depending on doPlot, plot either a square or a circle.
##
##-----------------------------------------------------------------------
proc sm_sq { x y delt thisColor outline tagName doPlot} {
        
      global  canvasWindow 
      
#     Calculate coords for small square.
       set x1 [expr {$x - $delt}]
       set y1 [expr {$y - $delt}]
       set x2 [expr {$x + $delt}]
       set y2 [expr {$y + $delt}]
       
       if {$doPlot ==1} {
          $canvasWindow create rectangle $x1 $y1 $x2 $y2 -fill $thisColor \
          -width 1 -outline $outline -tag $tagName
       } elseif {$doPlot ==2} {
           $canvasWindow create oval $x1 $y1 $x2 $y2 -fill $thisColor \
          -width 1 -outline $outline -tag $tagName
       }               

}


##------------------------------------------------------------------------------------
##  Proc square.
##
##  Draw a square cell for the integer sqNum, centered on x and y.  If sqNum is Prime,
##  enter the value of sqNum in Coarse grid, else use a '+' for Fine grid. Colorfill 
##  will be navy blue if integer is prime.  For Coarse grid, nonprime integers will
##  be written in slategray3.  Cells will be 2 * $delta in width.
##  Used in both the Sq and Tri systems.
##
##------------------------------------------------------------------------------------
proc square { x y } {
        
      global  canvasWindow delta foundPrime granularity sqNum xMin xMax yMin yMax

#  isPrime will determine whether the integer at x,y is Prime, based on list of primes.
      isPrime $x $y

#  Determine min max extents of X and Y.
      if {$xMin > $x} {
          set xMin $x
      } elseif {$xMax < $x} {
          set xMax $x
      }

      if {$yMin > $y} {
          set yMin $y
      } elseif {$yMax < $y} {
          set yMax $y
      }

      if {$foundPrime == 1} {
          set fgnd "navy blue"
          set weight bold
      } else {
         set fgnd "slategray3"
         set weight normal
      }

#     Calculate coords for Square.
      set x1 [expr {$x - $delta}]
      set y1 [expr {$y - $delta}]
      set x2 [expr {$x + $delta}]
      set y2 [expr {$y + $delta}]
      set outline lightblue1

#     Create square here.
      if {[string compare $granularity "fine"] == 0} {
      } elseif {[string compare $granularity "coarse"] == 0} {
          $canvasWindow create rectangle $x1 $y1 $x2 $y2 \
          -outline $outline -width 1
      }

#     For coarse granularity,  insert sqNum as text.
      if {[string compare $granularity "coarse"] == 0} {
         $canvasWindow create text $x $y -text $sqNum -fill $fgnd \
         -font "Times 9 $weight" 
      } elseif {[string compare $granularity "fine"] == 0} {
         if {$foundPrime == 1} {
            $canvasWindow create text $x $y -text "+" -font "Times 7" \
            -fill "navy blue"
         } 
      }

      incr sqNum

}


##-------------------------------------------------
##  Proc sq_GridFormulae
##
##  A proc  that contains some default formulae for
##  plotting Prime Predicting Trajectories in the
##  Square system.  These will appear in the
##  Formula listbox unless the file
##  sq_Formula_File.tcl exists.  Formulae will be
##  pulled from that file.

##-------------------------------------------------
proc sq_GridFormulae { } {
        
    global  formulae SQ_Formulas_Read

# 0  Principle Axes for Square System.
lappend formulae {"m * m" }

# 1  Only one branch with Primes.
lappend formulae {"m * m - 2" }

# 2  Only one branch with Primes.
lappend formulae {"m * m + 7" }

# 3  lagrange’s Formula.
lappend formulae {"m * m + m + 17" }

# 4  Variation on Euler.
lappend formulae {"m * m + m + 41" }

# 5  Only one branch with Primes.
lappend formulae {"m * m - 227" }

# 6    Collapsed to Lower right.
lappend formulae {"4 * m * m + 4 * m + 59" }

# 7  Spiral.
lappend formulae {"2 * m * m + 29" }

# 8  Euler like, three bends
lappend formulae {"m * m - m + 217" }

# 9  Euler’s Formula, no bends.
lappend formulae {"m * m - m + 41" }

# 10  Euler like, three bends, but further out.
lappend formulae {"m * m - m + 487" }

# 11  Collapsed to Upper right.
lappend formulae {"4 * m * m - 2 * m + 41" }

# 12  Collapsed to Lower left.
lappend formulae {"4 * m * m + 2 * m + 41" }

# 13  Collapsed to Lower right.
lappend formulae {"4 * m * m + 4 * m - 59" }

# 14  Square Empty.  Empty to the right
lappend formulae {"m * m - 1.5 * m" }

# 15  Square Empty.  Empty to the right
lappend formulae {"m * m - 1.5 * m - 1" }

# 16  Square Empty.  Empty Downward
lappend formulae {"m * m + 1.5 * m" }

# 17  Square Empty.  Empty Downward
lappend formulae {"m * m + 1.5 * m - 1" }

set SQ_Formulas_Read 1
   
}


##-------------------------------------------------
##  Proc Sq_iterate
##
##  A proc to write out the integers in Ulam order,
##  on a SQUARE grid.  Draw (2*$M -1) squares in  
##  an upside down L or backward L shaped pattern. 
##  Squares are drawn in Counter-ClockWise Order.
##    Proc square draws the square.
##-------------------------------------------------
proc Sq_iterate {M} {
        
    global  nextOp nucX nucY twoDelta sqNum

    set num_Moves [expr {$M -1}]
    set nextOp "right"
    if {[expr {fmod ($M,2)}] > 0.0} {
       set nextOp "left"
    }

    if {[string compare $nextOp "right"] == 0} {
       set nucX [expr {$nucX + $twoDelta}]
       square $nucX $nucY
       for {set i 1} {$i <= $num_Moves} {incr i} {
          set nucY [expr {$nucY - $twoDelta}]
          square $nucX $nucY
       }
       set cntr [expr {$sqNum -1}]
       for {set i 1} {$i <= $num_Moves} {incr i} {
          set nucX [expr {$nucX - $twoDelta}]
          square $nucX $nucY
       }
    } else {
          set nucX [expr {$nucX - $twoDelta}]
          square $nucX $nucY
          for {set i 1} {$i <= $num_Moves} {incr i} {
             set nucY [expr {$nucY + $twoDelta}]
             square $nucX $nucY
          }
          set cntr [expr {$sqNum -1}]
          for {set i 1} {$i <= $num_Moves} {incr i} {
             set nucX [expr {$nucX + $twoDelta}]
             square $nucX $nucY
          }
    }

}


##--------------------------------------------------------------------
##  Proc TridrawLine { start end color}.
##
##  Draw a line with color from the number start to the number end on 
##  the Triangular Format Screen.
## 
##---------------------------------------------------------------------
proc TridrawLine {start end color} {
        
      global  canvasWindow lastm tagName
     
      set coords {}
      set lastm 1
      set topCoords [getTriCoords $start $tagName 0]
      set lastm 1
      set bottomCoords [getTriCoords $end $tagName 0]

      set x1 [lindex $topCoords 0]
      set y1 [lindex $topCoords 1] 
      set x3 [lindex $bottomCoords 0]
      set y3 [lindex $bottomCoords 1]         
      lappend coords [list $x1 $y1 $x3 $y3]
      eval {$canvasWindow create line} $coords \
           {-tag $tagName  -width 2 -fill $color}
           
}


##-----------------------------------------------
##  Proc tri_GridFormulae
##
##  This proc contains some default formulae for
##  plotting Prime Predicting Trajectories in the
##  Triangular system.  These will appear in the
##  Formula listbox unless the file
#   tri_Formula_File.tcl exists.  Formulae will be
#   pulled from that file.
##-----------------------------------------------
proc tri_GridFormulae { } {
        
    global  formulae TR_Formulas_Read
 
# 0  Principle Axes for Triangular System.
lappend formulae {"m * (m + 1) / 2" }

# 1  Only one branch with Primes.
lappend formulae {"m * (m + 1) / 2 + 2" }

# 1  Only one branch with Primes.
lappend formulae {"m * (m + 1) / 2 - 5" }

# 2  Triangular Empty, Collapsed.  Empty to the right.
lappend formulae {"m * (9 * m - 7) / 2" }

# 3  Triangular Empty, Collapsed.  Empty to the left.
lappend formulae {"m * (9 * m - 17) / 2" }

# 4  Triangular Empty, Collapsed.  Diagonal to Bottom Right.
lappend formulae {"m * (9 * m - 11) / 2" }

# 5  Triangular Empty.  Only one Prime.
lappend formulae {"m * (m - 3) / 2 - 27" }

# 6  Variation on Euler.  Spiral in Triangular System.
lappend formulae {"m * m + m + 41" }

# 7  Bends as Branches cross Principle Axes.
lappend formulae {"m * (m + 1) / 2 + 157" }

# 8  Bends as Branches cross Principle Axes.
lappend formulae {"m * (m + 1) / 2 + 457" }

# 9  Bends further out as Branches cross Principle Axes.
lappend formulae {"m * (m + 1) / 2 + 757" }

# 10  Branches are antiparallel to Principle Axes.
lappend formulae {"2 * m * m + 29" }

# 11  Similar to Previous, but Branches are Parallel to Principle Axes.
lappend formulae {"m * (m + 1) / 2 + 62" }

# 12  Similar to Previous, Branches are Parallel to Principle Axes.
lappend formulae {"2 * m * m - 7 * m - 157" }

# 13  Totally Empty.  Mirror image of Principle Axes.
lappend formulae {"2 * m * m + 2" }

set TR_Formulas_Read 1

}


##---------------------------------------------------------
##  Proc Tri_iterate
##
##  A proc to write out the integers in Ulam order,
##  but on a TRIANGULAR grid.  Squares are drawn in 
##  Counter-ClockWise order.  Proc square draws the square.
##---------------------------------------------------------
proc Tri_iterate {M} {
        
      global  delta nextOp nucX nucY twoDelta
    
      if {[string compare $nextOp "tri_rt"] == 0} {
         set nucX [expr {$nucX + $twoDelta}]
         set nucY $nucY
         square $nucX $nucY

         for {set j 1} {$j <= $M} {incr j} {
            set nucX [expr {$nucX -$delta}]
            set nucY [expr {$nucY - $twoDelta}]
            square $nucX $nucY
         }
         set nextOp "tri_up"
         return
      }

      if {[string compare $nextOp "tri_up"] == 0} {
         set nucX [expr {$nucX -$delta}]
         set nucY [expr {$nucY - $twoDelta}]
         square $nucX $nucY

         for {set j 1} {$j <= $M} {incr j} {
            set nucX [expr {$nucX - $delta}]
            set nucY [expr {$nucY + $twoDelta}]
            square $nucX $nucY
         }
         set nextOp "tri_dn"
         return
      }

      if {[string compare $nextOp "tri_dn"] == 0} {
         set nucX [expr {$nucX - $delta}]
         set nucY [expr {$nucY + $twoDelta}]
         square $nucX $nucY

            for {set j 1} {$j <= $M} {incr j} {
            set nucX [expr {$nucX + $twoDelta}]
            set nucY $nucY
            square $nucX $nucY
         }
         set nextOp "tri_rt"
         return
      }

}


controlsSetup

Primer.tcl edit

#
#
#
##  How to run it--
#
#-- ./Primer.tcl
#
#   ---   Compute all primes that are less than:  2000
#
#   There are 303 primes less than 2000
#
# Done


#
#!/bin/sh
# \
exec wish "$0" ${1+"$@"}

#
#  Version of May 4, 2017
#


   set primes {}

   puts -nonewline "\n   ---   Compute all primes that are less than:  "
   flush stdout
       
   set max [gets stdin]
   if {$max < 2} {
       set max 2
   }

   set primes [list 2]
   for {set test 3} {$test <= $max} {incr test 2} {
      set maxTest [expr {int(sqrt($test))}]
      foreach prime $primes {
         if {$prime  > $maxTest} {
            lappend primes $test
               break
         }
         if {![expr {$test % $prime}]} {
            break
         }
      }
   }

   
 
   set strng "#  The Prime Numbers less than  $max \n# \nset primes { \n"
  
   set strngLen 2
   set f [open "PrimesList" w]

   foreach n $primes {
      if {$strngLen > 75} {
         puts $f $strng
         set strng {}
         set nLen [string length "$n "]
         set strngLen $nLen 
         append strng "$n "
      } else {
         set nLen [string length "$n "]
         incr strngLen $nLen
         append strng "$n "
      }
   }
   append strng "\n}"
   puts $f $strng
   close $f

   puts "\n   There are [llength $primes] primes less than $max \n"

exit



#======================== Output from Primer.tcl ===========================

#
#  The Prime Numbers less than  2000 
# 
set primes { 
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 
103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 
199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 
313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 
433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 
563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 
673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 
811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 
941 947 953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049 
1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 
1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 
1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423 
1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 
1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 
1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 
1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 
1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 1999 
}

#   There are 303 primes less than 2000
#
#

——

sq_Formula_File.tcl edit

——
#
#
#
#


#  Following two have same Potency of 0.585 for Primes LT 100K
lappend formulae {"m * m - 7 * m - 97"}
lappend formulae {"m * m + 7 * m - 97"}
#  Following two have same Potency of 0.148 for Primes LT 100
lappend formulae {"m * m - 7 * m + 97"}
lappend formulae {"m * m + 7 * m + 97"}


#  Variations on a Theme.  What happens when linear term in Formula is varied.
lappend formulae {"m * m - m - 97"}
lappend formulae {"m * m - 2 * m - 97"}
lappend formulae {"m * m - 3 * m - 97"}
lappend formulae {"m * m - 4 * m - 97"}
lappend formulae {"m * m - 5 * m - 97"}
lappend formulae {"m * m - 6 * m - 97"}
lappend formulae {"m * m - 7 * m - 97"}
lappend formulae {"m * m - 8 * m - 97"}

#  More variations
lappend formulae {"m * m - 7 * m - 313"}
lappend formulae {"m * m - 8 * m - 127"}
lappend formulae {"m * m - 8 * m - 277"}


#  These are best viewed with the PLT 500K Data Set
lappend formulae {"m * m - 225"}
lappend formulae {"m * m - 235"}
lappend formulae {"m * m - 237"}
lappend formulae {"m * m - 239"}
lappend formulae {"m * m - 240"}
lappend formulae {"m * m - 241"}
lappend formulae {"m * m - 253"}
lappend formulae {"m * m - 257"}
lappend formulae {"m * m - 271"}
lappend formulae {"m * m - 283"}
lappend formulae {"m * m - 295"}
lappend formulae {"m * m - 371"}
lappend formulae {"m * m - 971"}
lappend formulae {"m * m - 1372"}


#  Other interesting Formulae
lappend formulae {"4 * m * m+ 4 * m + 409"}

lappend formulae {"m * m+ m + 409"}

lappend formulae { "m * m - 7 * m - 97"}

lappend formulae {"m * m - 2 * m - 41" }

lappend formulae {"m * m - 3 * m - 41" }

lappend formulae {"m * m - 4 * m - 41" }


#  Almost the same trajectories. Collapsed into one Branch.
lappend formulae {"4 * m * m + 4 * m + 59"}

lappend formulae {"4 * m * m - 4 * m + 59"}

#  Almost the same trajectories. Collapsed into one Branch.
lappend formulae {"4 * m * m + 4 * m - 59"}

lappend formulae {"4 * m * m - 4 * m - 59"}

#  More Collapsed trajectories that are into one Branch.
lappend formulae {"4 * m * m + 3 * m + 59"}

lappend formulae {"4 * m * m - 3 * m + 59"}

lappend formulae {"4 * m * m + 3 * m - 59"}

lappend formulae {"4 * m * m - 3 * m - 59"}
#
#
#
#
#

——

tri_Formula_File.tcl edit

——
#
#
#
#
#
#  Following have almost the same trajectory.
lappend formulae {"m * (m + 1) / 2 + 257" }

lappend formulae {"2 * m * m + 3 * m + 257"}

#
#   Following has primes on lines parallel to all three branches.
lappend formulae {"m * (m + 1) / 2 + 4" }

#  Following has primes on lines parallel to branches 1 and 2.
lappend formulae {"m * (m + 1) / 2 - 4" }

#  Following has primes on lines parallel to all three branches.
lappend formulae {"m * (m + 1) / 2 - 5" }

#   Following has primes on lines parallel to all three branches.
lappend formulae {"m * (m + 1) / 2 + 7" }

lappend formulae {"m * (m + 1) / 2 + 57" }

lappend formulae {"m * (m - 1) / 2 + 57" }

lappend formulae {"m * (2 * m + 1) / 2 + 57" }

#       Variations on a Theme.  Best used with PLT 500K Primes List
lappend formulae {"m * (m + 1) / 2 + 57" }

lappend formulae {"m * (m + 1) / 2 + 157" }

lappend formulae {"m * (m + 1) / 2 + 257" }

lappend formulae {"m * (m + 1) / 2 + 357" }

lappend formulae {"m * (m + 1) / 2 + 457" }

lappend formulae {"m * (m + 1) / 2 + 557" }

lappend formulae {"m * (m + 1) / 2 + 657" }

lappend formulae {"m * (m + 1) / 2 + 757" }


#  Following can be viewed with PLT 100K Primes List
lappend formulae {"2 * m * m + 3 * m + 59"}

lappend formulae {"2 * m * m + 4 * m + 59"}


#  Variations on a theme.  Modifying the constant term.
lappend formulae {"m * (m + 1) / 2 + 2"}

lappend formulae {"m * (m + 1) / 2 + 12"}

lappend formulae {"m * (m + 1) / 2 + 22"}

lappend formulae {"m * (m + 1) / 2 + 32"}

lappend formulae {"m * (m + 1) / 2 + 42"}

lappend formulae {"m * (m + 1) / 2 + 52"}

lappend formulae {"m * (m + 1) / 2 + 62"}

lappend formulae {" m * (m + 1) / 2 + 72 "} 

lappend formulae {" m * (m + 1) / 2 + 82 "} 

lappend formulae {" m * (m + 1) / 2 + 92 "} 

lappend formulae {" m * (m + 1) / 2 + 102 "} 

lappend formulae {" m * (m + 1) / 2 + 112 "} 

#
#
#
#


Category Graphics[Category Prime Numbers][Category Ulam Spirals]