C Program to Plot the Gamma Function in the Terminal

In this post I want to talk about a C program I wrote just recently that plots a mathematical function – specifically the gamma function. I think it’s worth looking at, because this program demonstrates how to handle the various aspects of graphing and plotting using just ASCII characters in the terminal. The program draws a pair of axes and then plots the function using asterisks at the proper height for each x value.

The program I have written makes use of libm, which is a library for mathematical functions. A lot of the symbols in math.h and complex.h (including the tgamma function used in my program) are actually defined here, not in libc. So given that the filename of my program is gamma.c, the command to compile it would be:


$ gcc -o gamma-plot gamma.c -lm

The crux of this program is the way it calculates the proper height for each asterisk in the graph based on the parameters given at the command line. These parameters include the width and height of the graph in characters as well as the maximum and minimum values for both x and y. If these are not specified at the command line, default values are selected. An array called graph is used to keep track of the y values. After some error checking, the values in this array are set to integers giving the exact height (row) of each asterisk for each given column. Axes are drawn, and then a graph is plotted in real time using 1/10 second delays between each print operation. A print operation is carried out by using ANSI escape sequences to move the cursor to a specific row and column, then printing an asterisk and flushing the output buffer.

The complete code for the program is as follows:


  1 // Program to plot the gamma function
  2 // in the terminal window
  3 
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 #include <string.h>
  8 #include <math.h>
  9 
 10 void usage(){
 11         puts"Usage:" );
 12         puts"gamma-plot {key=value}" );
 13         puts"Possible keys:" );
 14         puts"\txmin\tMinimum x value" );
 15         puts"\txmax\tMaximum x value" );
 16         puts"\tymin\tMinimum y value" );
 17         puts"\tymax\tMaximum y value" );
 18         puts"\twidth\tWidth of grid in characters" );
 19         puts"\theight\tHeight of grid in characters" );
 20 }
 21 
 22 int mainint argc, char **argv ){
 23         int i;
 24         char *key;
 25         char *val;
 26         double xmin = -10, ymin = -10, xmax = 10, ymax = 10;
 27         double xinc, yinc;              // increments for x and y
 28         int width = 80, height = 25;    // width and height of the graph
 29         double xval;                    // raw x value
 30         double *yval;                   // raw y value
 31         int *graph;                     // scaled y values
 32         int xmiddle, ymiddle;           // Coordinates for the center of the screen
 33         // Parse command line parameters:
 34         for( i = 1; i < argc; i++ ){
 35                 if( !strcmp( argv[i], "--help" ) || !strcmp( argv[i], "-h" ) ){
 36                         usage();
 37                         exit0 );
 38                 }
 39                 key = strtok( argv[i], "=" );
 40                 val = strtokNULL"\0" );
 41                 if( !strcmp( val, "" ) ){ // no = sign in parameter, or = sign at the end
 42                         fprintfstderr"%s: Options must be in key=value format.\n", argv[0] );
 43                         exit( -1 );
 44                 }
 45                 else if( !strcmp( key, "xmin" ) )
 46                         xmin = atof( val );
 47                 else if( !strcmp( key, "ymin" ) )
 48                         ymin = atof( val );
 49                 else if( !strcmp( key, "xmax" ) )
 50                         xmax = atof( val );
 51                 else if( !strcmp( key, "ymax" ) )
 52                         ymax = atof( val );
 53                 else if( !strcmp( key, "width" ) )
 54                         width = atof( val );
 55                 else if( !strcmp( key, "height" ) )
 56                         height = atof( val );
 57                 else{
 58                         usage();
 59                         exit( -1 );
 60                 }
 61         }
 62         if( xmin >= xmax || ymin >= ymax || width <= 0 || height <= 0 ){
 63                 fprintfstderr"%s: Invalid values for arguments\n", argv[0] );
 64         }
 65         // Populate graph with values:
 66         yval = (double *) calloc( width, sizeofdouble ) );
 67         graph = (int *) calloc( width, sizeofint ) );
 68         xinc = (xmax - xmin) / width;
 69         yinc = (ymax - ymin) / height;
 70         for( i = 0; i < width; i++ ){
 71                 xval = xmin + xinc * i;
 72                 yval[i] = tgamma( xval );
 73                 graph[i] = round( (yval[i] - ymin) / yinc );
 74         }
 75         printf"\e[2J" ); // Clear screen
 76         fflushstdout );
 77         // Draw x axis:
 78         ymiddle = round( height / 2 );
 79         for( i = 1; i <= width; i++ )
 80                 printf"\e[%d;%dH-", ymiddle, i );
 81         // Draw y axis:
 82         xmiddle = round( width / 2 );
 83         for( i = 1; i <= height; i++ )
 84                 printf"\e[%d;%dH|", i, xmiddle );
 85         // Draw axis decorations:
 86         printf"\e[%d;%dH^"1, xmiddle );
 87         printf"\e[%d;%dHv", height, xmiddle );
 88         printf"\e[%d;%dH<", ymiddle, 1 );
 89         printf"\e[%d;%dH>", ymiddle, width );
 90         printf"\e[%d;%dH+", ymiddle, xmiddle );
 91         fflushstdout );
 92         usleep100000 );
 93         // Plot gamma function:
 94         for( i = 0; i < width; i++ ){
 95                 printf"\e[%d;%dH", height - graph[i] + 1, i + 1 );
 96                 if( graph[i] >= 0 && graph[i] <= height ) putchar'*' );
 97                 fflushstdout );
 98                 usleep100000 );
 99         }
100         printf"\e[%d;%dH", height, width );
101         putchar'\n' );
102         return 0;
103 }

Here’s a screenshot of the output:

Plotting the gamma function in the terminal

Yeah, I know this was kind of a low-effort post, but bear with me. I’ve been rather busy with real-world stuff lately – trying to get my life back together and on-track now that the pandemic is over, as well as dealing with some medical issues – and I haven’t had much time to focus on tech projects or blogging. I want to continue posting one new article every week though, and hopefully I’ll be able to devote more time to it in the future. Until then, farewell and happy coding.

One thought on “C Program to Plot the Gamma Function in the Terminal

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s