In a previous blog post we covered how to generate the basemap of a Ulam spiral by using a C++ script in Code Builder. In this post we’ll be appending that script with some basic functions allowing you to display prime numbers, odd numbers, and numbers divisible by specific integers. We’ll then plot the resulting matrices and show you how to create a basic GUI for calling these different functions. You can view the end result of this blog by downloading the .cpp and .opj files here.

With the way this script has been structured it is very easy for us to add additional functions that rely on our CSpiral function but can be added without modifying it.

Between the //CSpiral and //UlamSpiral sections of our basic script, add the following

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
//---------------------------------------------------------------------------- // CPrimeSpiral // This class does a spiral and checks if the cell index is a prime number. // If it is prime the cell is set to the index else it is set to zero. //---------------------------------------------------------------------------- class CPrimeSpiral : public CSpiral { public: int Equation() { m_M[m_row][m_col] = IsPrime(m_index) ? m_index : NANUM; return 0; // If the boolean function IsPrime is true, this function returns its value to the matrix // If the function is false, it returns the missing value variable "NANUM" } bool IsPrime(int n) { double sr = sqrt(n); for( int i = 2; i <= sr; i++ ) // This takes the square root of the number in question, then runs through the numbers between 2 // and this square root in whole integer increments, represented by i++ { if( (n % i) == 0 ) return false; } return true; } // The values between 2 and the square of the number are then returned and divided by the // number itself. For those not familiar with the use of the percentage symbol in C++, // it serves as a division operator, returning the remainder of an expression. }; |

Then we’ll need to update the UlamSpiral function to be able to call this script as one of our options; for this reason the end of our script will now appear as such, note the comments in CAPS-

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//---------------------------------------------------------------------------- // UlamSpiral // The main function for calling the different types of spirals. //---------------------------------------------------------------------------- enum { UlamSpiral_Help = 0, UlamSpiral_Index, UlamSpiral_Prime, // ADD THIS SINGLE LINE AFTER _Index UlamSpiral_Unknown }; int UlamSpiral(int type = 0) { switch( type ) { case UlamSpiral_Help: printf("%d = Help\n", UlamSpiral_Help); printf("%d = Index\n", UlamSpiral_Index); printf("%d = Prime Numbers\n", UlamSpiral_Prime); break; case UlamSpiral_Index: { CSpiral spiral; spiral.Run(); } break; case UlamSpiral_Prime: // ADD THIS CASE SECTION AFTER "BREAK;" STARTING FROM THIS LINE { CPrimeSpiral spiral; spiral.Run(); } break; } return 0; // TO THIS LINE } |

Once this updated script has been built, create a new matrix or open an existing one. Then in the main menu go to Matrix>Set Matrix Dimension/Labels…, and set its dimensions to 100×100 or 200×200. This will allow us to better view the frequency of prime numbers in our spiral. Next open the Script Window and type “UlamSpiral(2)”. If the script works you should see that it generated a spiral that displays only those numbers which are primes, whereas those that are not are displayed as missing numbers (–).

Now that we have our prime values, let’s plot them. Select the whole matrix, and go to Plot>Contour/Heat Map>Heat Map. At first you should see a blank plot with “Speed Mode is On” emblazoned across the graph. To change this, simply click on the little running man icon that looks like this to turn off Speed Mode. By default this button should appear on the upper right-hand side of your workspace, next to the rescale button. Your graph should now appear like so-

As an aside–

While our matrix is 200 by 200 cells in size, it’s important to note that the size of the matrix represents an index that is not directly tied to the x and y values of the graph. If you go back into the matrix and then in the main menu select “Matrix>Set Matrix Dimension/Labels…” you’ll see that in columns are mapped for x values from 1 to 10 by default. There is however no reason to change the mapping values as the axes are meaningless in this context anyway.

Next select and delete the axes, scale, titles, and color scale if you so choose. Since our series is being displayed as a spiral, these numbers bear no meaning. To make our graph more legible, double click on the heat map to open the Plot Details dialog and then in the Colormap/Contours tab change the Missing Values color from the default to either White or None. After clicking okay, you may want to change the color palette to something that contrasts with the white background. For the purposes of our example, I would recommend selecting the “Blue”, “Green” or “Red” palettes that appear in Origin 2016’s new palette menu.

Now that we can visualize our spiral, let’s add one last feature to our script. Say we want to design a basic input function, allowing users to view patterns generated by different denominators. In this case our function script, added between //CPrimeSpiral and the //UlamSpiral calling function, will look very simple-

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//---------------------------------------------------------------------------- // CDivBySpiral // //---------------------------------------------------------------------------- class CDivBySpiral : public CSpiral { public: int Equation() { m_M[m_row][m_col] = m_index % divisor ? NANUM : m_index; // For each cell, if the m_index returns a remainder when divided by the divisor, display a missing // number (NANUM), otherwise return the index number return 0; } int divisor; }; |

Our UlamSpiral calling function will then be updated to place another line in our “enum” section, like so-

1 2 3 4 5 6 7 |
enum { UlamSpiral_Help = 0, UlamSpiral_Index, UlamSpiral_Prime, UlamSpiral_DivBy, // ADD THIS LINE HERE UlamSpiral_Unknown }; |

and then adding the following-

1 2 3 |
// printf("%d = Divisible by\n", UlamSpiral_DivBy); // |

after the “printf UlamSpiral_Prime” line and before the “break”. Then after the “case UlamSpiral_Prime” “break;” and before the next bracket }, add-

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
case UlamSpiral_DivBy: { GETN_BOX(tr); GETN_NUM(Divisor, "Divisor", 1); // Triggers an input box which lists 1 by default, allows user to enter any integer if( GetNBox(tr) ) { CDivBySpiral spiral; spiral.divisor = tr.Divisor.dVal; spiral.Run(); } // If an integer is entered, this will call CDivBySpiral function based on the divisor given } break; |

Compile the updated script, and with the matrix window active (as opposed to the heat map), go to the script window and type UlamSpiral(3). You should see this dialog box-

Enter any integer, in this case we’ll type in 7, and then after the matrix changes you should find that your heatmap has updated as well to show the distribution of those numbers which can be divided by 7. This example isn’t especially practical but rather shows how you can add user inputs to display different series on your spiral.

These are some simple examples of how OriginC scripting can be used to illustrate different series of numbers. If you know C programming, you should be able to add your own functions to the script to show “odious” numbers or other series and call them from the UlamSpiral function as another option. UIam spirals are especially useful as a teaching tool for showing the behavior of other complex number series that may not illustrate clear patterns over a single number line. You can learn more about these and similar number spirals on many math reference sites all across the internet.

The code given here is really easy to use through which you can create -Ulam-spirals. This is the best programming to create Ulam spirals in c language.