Pages

30 March 2013

learning fortran

I've decided that a person with a science degree is probably lacking if s?he doesn't know a bit of Fortran, so I've taken the liberty of teaching myself by following the tutorial available a Fortran Tutorial. I ran into a bit of a snag on Exercise 6.3 on the Subroutines and Functions lesson. For some reason I couldn't get the subroutine to work the way I wanted. I knew the algorithm for the finite difference matrix itself was correct, but it kept crashing on me

I'm using gfortran on both my workstation and on my android device, but they both seem to work differently when it comes to arrays and fortran procedural programming and I think gcc on my android is broken. This only made things more frustrating for me, so I began to do a lot of reading on Fortran 95 and how it handles arrays, functions and the like while trying things out.

Happily, I was able to figure it out but it only works on my workstation. It's too bad the gcc android port I'm using is broken, I'll have to find a replacement. Anyhow, here is the code I was able to cobble together. Try not to be too critical.


program exercise6_3
    !print out a finite difference matrix using a function
    implicit none
    integer :: row, col, length
    integer, allocatable, dimension(:,:) :: matrix 
    print *, 'How big is your nxn matrix?'
    read *, length

    allocate(matrix(length, length))
    call d_matrix(length, matrix)

    do row = 1, length
          write(*, 10) (matrix(row, col), col = 1, length)
    end do

    10 format(100i2)

    deallocate(matrix)

    end program exercise6_3

    subroutine d_matrix(count, array)
    !finite difference matrix
        implicit none
        integer :: count, m
        integer, dimension(count,count) :: array
        !array dimensions must be specified

        array = 0
        do m = 1, count
              array(m, m) = 2
              if ( m /= count ) then
                    array(m, m + 1) = -1
                    array(m + 1, m) = -1
                end if
        end do

        end subroutine d_matrix

19 March 2013

fun with a basic algorithm

On Twitter Ed announced that he was playing around with a BASIC program that ran on the venerable Commodore 64. I myself am not a professional programmer, but I've taken several programming courses and have played with code from time to time. I fondly remember programming instructions in BASIC or Pascal on the school computers and was always a bit saddened that my home didn't have one for our personal use.

Naturally, Ed posting about 10 PRINT made me curious. Since I run OpenBSD on my workstation I don't have a native version of BASIC, but I do have a C compiler in the form of GCC. So I set out to port "10 PRINT" in C.

10 PRINT

The Code

10 PRINT CHR$(205.5+RND(1)); : GOTO 10

10 PRINT Output - Frodo C64 Emulator

My First Porting Attempts

The variant of UNIX that I doesn't have the PETSCII character set that the Commodore 64 uses in the 10 PRINT program. As a result my first attempts used the slash "/" and the backslash "\" characters from the standard ASCII library.

maze.c


/* auto maze generator */

#include <stdio.h>
#include <stdlib.h>

/* print to screen the backslash or forward
 * slash depending if the value of i is
 * odd or even. */

int main (int argc, char *argv[])
{
        do {
                int i = random();

                if ( i%2 == 0 )
                        printf ("\\");
                else
                        printf ("/");

        } while ( 1 );

        return 0;
}

maze1.c


/* auto maze generator, mk1 */

#include <stdio.h>
#include <stdlib.h>

/* determine if the number passed is
 * odd or even and return result. */

int odd_even (number)
        int number;
{
        if ( number % 2 == 0)
                return 0;
        else
                return 1;
}

/* print the forward slash or backslash
 * depending on returned result. */

int main (int argc, char *argv[])
{
        do {
                int i = random();

                if ( odd_even(i) == 0 )
                        printf ("\\");
                else
                        printf ("/");

        } while ( 1 );

        return 0;
}

maze2.c


/* auto maze generator, mk3 */

#include <stdio.h>
#include <stdlib.h>

/* print to screen the backslash or forward
 * slash depending if the value of i is
 * odd or even. */

int main (int argc, char *argv[]){do {int i = random();if (i%2==0) printf("\\");else printf("/");}while(1);return 0;}

Output of First Attempts

My Following Attempts

I wasn't satisfied with the use of slash and back slash to build the output. While using slash and backslash approximated the output of 10 PRINT somewhat, it was obvious that the approximation was lacking. Fortunately, it turns out that Unicode has a solution that more approximates the diagonal lines used in PETSCII. The right leaning line has the Unicode symbol

0x2571
and the left leaning line has the symbol
0x2572
in C. So, using those symbols I modified my code accordingly. I also used an terminal emulator that was capable of rendering the Unicode symbols I was using to view my output, in this case Gnome Terminal.

maze4.c


/* auto maze generator, mk4 */

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

/* print the forward slash or backslash
 * depending on returned result. */

int main (int argc, char *argv[])
{
        char *locale;
        locale = setlocale (LC_CTYPE, "en_US.UTF-8");
        int i;

        while (1) {
                wprintf (L"%lc", (i = 2571.5 + arc4random_uniform(2), i == 2571) ? L'\x2571' : L'\x2572');
        }

        printf ("\n");

        return 0;
}

maze5.c


/* auto maze generator, mk5 */

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

/* Adds a value 0 < x < 1 to passed float
 * value and return an integer. */

int find_value (given)
        float given;
{
        given = given + arc4random_uniform(2);
        return (given);
}

/* print the forward slash or backslash
 * depending on returned result. */

int main (int argc, char *argv[])
{
        char *locale;
        locale = setlocale (LC_CTYPE, "en_US.UTF-8");
        int i;

        while (1) {
                wprintf (L"%lc", (i = find_value(2571.5), i == 2571) ? L'\x2571' : L'\x2572');
        }

        printf ("\n");

        return 0;
}

Output of Following Attempts

Thoughts

I find the original algorithm in C64 BASIC interesting for a couple of reasons.

  1. The entire script is one line.
  2. The script uses a 'goto' statement.
  3. The script takes advantage of how characters are defined in PETSCII

If I were to do this properly in C I would either have to have a similar set of characters that I could call on, or I would have to call on C's graphical abilities and define line segments for various values in the algorithm.

The fact that there are two opposing slash characters in Unicode that are numerically adjacent to each other is fortuitous. I don't know if the spec for Unicode came before 10 PRINT and PETSCII or after, but I suspect that if it's the latter then perhaps the designers were influenced by 10 PRINT? This is something that I may have to look into a bit, just to satisfy my curiosity.