home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / QC25-10.ZIP / SAMPLES / MATHDEMO.C$ / MATHDEMO.bin
Encoding:
Text File  |  1989-04-28  |  10.9 KB  |  377 lines

  1. /* MATHDEMO.C - Creates a simple on-screen calculator with functions for
  2.  * basic integer arithmetic and for solving for the roots of a quadratic
  3.  * equation. MATHDEMO invokes QuickAssembler procedures that illustrate
  4.  * assembly-language instructions related to mathematics, including those
  5.  * specific to the 8087 family of coprocessors.
  6.  *
  7.  * MATHDEMO.EXE is built from the following files:
  8.  *    MATHDEMO.C - Main program
  9.  *    MATH.ASM     - QuickAssembler procedures for MATHDEMO
  10.  *    COMMON.ASM - QuickAssembler procedures shared by other example programs
  11.  *    DEMO.INC     - Assembly include file with macros and structure declarations
  12.  *    DEMO.H     - C include file with prototypes and structure declarations
  13.  *
  14.  * Procedures:    AddLong       MulLong      DivLong     Quadratic
  15.  *        SubLong       ImulLong     IdivLong
  16.  */
  17.  
  18. #include "demo.h"
  19. #include <dos.h>
  20. #include <conio.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23.  
  24. /* Function prototypes */
  25. void display_calc( void );
  26. void display_help( void );
  27. void press( void );
  28. void push( int sign );
  29.  
  30. /* Global variables */
  31. long s1, s2, s3;        /* Stack values: 1st, 2nd, 3rd        */
  32. char entry[11];         /* Entry window string            */
  33. int  col;            /* Current display column for entry */
  34.  
  35. main()
  36. {
  37.     int ch, err;            /* Keyboard character, return val  */
  38.     static int sign, mode;        /* Sign flag, signed/unsigned flag */
  39.     static float root1, root2;        /* Roots of quadratic equation       */
  40.     static short quotient, remainder;    /* Results of division           */
  41.     static long *product, result;
  42.     static char *rmsg[2] = { "roots", "indeterminate" };
  43.     static char *highmsg = { "high:" };
  44.     static char *lowmsg  = { "low:" };
  45.  
  46.     GetVidConfig();
  47.     display_calc();
  48.     StrWrite( 9, 14, "+" );
  49.     col = 20;
  50.     while( ch != ESCAPE )
  51.     {
  52.     SetCurPos( 9, col );
  53.     ch = getch();
  54.     switch( (ch = toupper( ch )) )
  55.     {
  56.         /* Display number in entry window. */
  57.         case '0':
  58.         case '1':
  59.         case '2':
  60.         case '3':
  61.         case '4':
  62.         case '5':
  63.         case '6':
  64.         case '7':
  65.         case '8':
  66.         case '9':
  67.         putch( (char) ch );
  68.         entry[col - 20] = (char) ch;
  69.         entry[++col - 20] = 0;
  70.         if( col == 30 )
  71.             col--;
  72.         break;
  73.  
  74.         /* Toggle between signed and unsigned arithmetic modes. */
  75.         case 'M':
  76.         if( mode )
  77.         {
  78.             mode = 0;            /* For signed mode,   */
  79.             StrWrite( 14, 57, "  (" );    /*   toggle flag off  */
  80.             StrWrite( 9, 14, "+" );    /*   and restore sign */
  81.         }
  82.         else
  83.         {
  84.             mode++;            /* For unsigned mode, */
  85.             StrWrite( 14, 57, "(un" );    /*   toggle flag on   */
  86.             StrWrite(  9, 14, " " );    /*   and blank sign   */
  87.         }
  88.         sign = 0;
  89.         break;
  90.  
  91.         /* Solve for x in quadratic equation s3*x*x + s2*x + s3 = 0. */
  92.         case 'Q':
  93.         push( sign );
  94.         err = Quadratic( (float)s3, (float)s2, (float)s1,
  95.                   &root1, &root2 );
  96.         ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry window    */
  97.         ClearBox( 7, 9, 49, 10, 66 );    /* Clear result window    */
  98.         if( err < 2 )
  99.         {
  100.             SetCurPos( 9, 50 );
  101.             printf( "%16.3f", root1 );        /* Display 1st root */
  102.             if( !err )
  103.             {
  104.             SetCurPos( 10, 50 );
  105.             printf( "%16.3f", root2 );    /* Display 2nd root */
  106.             }
  107.         }
  108.         if( err == 2)
  109.         {
  110.             StrWrite(  9, 50, rmsg[0] );   /* Display "roots    */
  111.             StrWrite( 10, 50, rmsg[1] );   /*    indeterminate"    */
  112.         }
  113.         break;
  114.  
  115.         /* Change sign. */
  116.         case 'S':
  117.         if( !mode )        /* Allow sign changes only */
  118.         {            /* in signed mode       */
  119.             if( sign )
  120.             {
  121.             StrWrite( 9, 14, "+" );
  122.             sign = 0;
  123.             }
  124.             else
  125.             {
  126.             StrWrite( 9, 14, "-" );
  127.             sign++;
  128.             }
  129.         }
  130.         break;
  131.  
  132.         /* Clear stack, reinitialize variables. */
  133.         case 'C':
  134.         s3 = s2 = s1 = 0;
  135.         ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry window  */
  136.         ClearBox( 7, 9, 49, 10, 66 );    /* Clear result window */
  137.         entry[0] = 0;
  138.         col = 20;
  139.         break;
  140.  
  141.         /* Push values down stack when Enter key pressed. */
  142.         case CR:
  143.         push( sign );
  144.         break;
  145.  
  146.         /* Display help screen. */
  147.         case '?':
  148.         case 'H':
  149.         display_help();         /* Display help     */
  150.         display_calc();         /* Redisplay calculator */
  151.         StrWrite( 9, 20, entry );    /*   and entry number    */
  152.         if( mode )
  153.         {
  154.             StrWrite( 14, 57, "(un" );    /* Make "unsigned"    */
  155.             StrWrite(  9, 14, " " );    /*   and blank sign    */
  156.         }
  157.         else
  158.         {
  159.             if( sign )
  160.             StrWrite( 9, 14, "-" );
  161.             else
  162.             StrWrite( 9, 14, "+" );
  163.         }
  164.         break;
  165.  
  166.         /* Add or subtract s1 and s2. */
  167.         case '+':
  168.         case '-':
  169.         push( sign );
  170.         if( (char) ch == '+' )
  171.             s1 = AddLong( s1, s2 );
  172.         else
  173.             s1 = SubLong( s2, s1 );
  174.         ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry window    */
  175.         ClearBox( 7, 9, 49, 10, 66 );    /* Clear result window    */
  176.         SetCurPos( 9, 56 );
  177.         if( mode )
  178.             printf( "%lu", s1 );    /* Display unsigned or    */
  179.         else
  180.             printf( "%li", s1 );    /*   signed result    */
  181.         break;
  182.  
  183.         /* Multiply s1 and s2. */
  184.         case '*':
  185.         push( sign );
  186.         if( mode )
  187.             product = MulLong(    s1, s2 );
  188.         else
  189.             s1        = ImulLong( s1, s2 );
  190.         ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry window    */
  191.         ClearBox( 7, 9, 49, 10, 66 );    /* Clear result window    */
  192.         if( mode )
  193.         {
  194.             StrWrite(  9, 50, highmsg );
  195.             StrWrite( 10, 50, lowmsg );
  196.             SetCurPos( 9, 56 );
  197.             printf( "%lu", *++product ); /* Display high and low   */
  198.             SetCurPos( 10, 56 );     /*   double-word of       */
  199.             printf( "%lu", *--product ); /*   unsigned product       */
  200.             s1 = *product;         /* Copy low word to stack */
  201.         }
  202.         else
  203.         {
  204.             SetCurPos( 9, 56 );
  205.             printf( "%li", s1 );    /* Display signed product  */
  206.         }
  207.         break;
  208.  
  209.         /* Divide s2 by s1. */
  210.         case '/':
  211.         push( sign );
  212.         if( mode )
  213.             quotient = DivLong(  s2, (int) s1, &remainder );
  214.         else
  215.             quotient = IdivLong( s2, (int) s1, &remainder );
  216.         ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry            */
  217.         ClearBox( 7, 9, 49, 10, 66 );    /* Clear result         */
  218.         if( abs( (int) remainder ) >= (abs( (int) s1 ) >> 1) )
  219.         {
  220.             if( quotient >= 0 )     /* Round up if        */
  221.             quotient++;        /*   remainder > s1/2   */
  222.             else
  223.             quotient--;
  224.         }
  225.         SetCurPos( 9, 56 );
  226.         if( mode )
  227.             printf( "%u", quotient );    /* Display result */
  228.         else
  229.             printf( "%i", quotient );
  230.         s1 = (long) quotient;        /* Copy quotient to stack */
  231.         break;
  232.  
  233.     }
  234.     }
  235.  
  236.     clear_scrn( 7, 0, 24 );        /* Clear screen before exit   */
  237.     SetCurPos( 23, 0 );         /*   and set cursor to bottom */
  238.     return( 0 );
  239. }
  240.  
  241.  
  242. /* display_calc - Clears screen and displays calculator.
  243.  *
  244.  * Params:  None
  245.  */
  246.  
  247. void display_calc( void )
  248. {
  249.     static char *calculator[19] =
  250.     {
  251.    "               ***   QuickAssembler Math Demonstration Program  ***",
  252.    "",
  253.    "",
  254.    "┌─ Integer Calculator ───────────────────────────────────────────────────┐",
  255.    "│                                                                        │",
  256.    "│         ┌────────────────┐                 ┌──────────────────┐        │",
  257.    "│         │                │                 │                  │        │",
  258.    "│         └────────────────┘                 │                  │        │",
  259.    "│                      entry                 └──────────────────┘        │",
  260.    "│                                                          result        │",
  261.    "│         7  8  9      +   -                 ? = Help                    │",
  262.    "│                                            M = Mode   (signed)         │",
  263.    "│         4  5  6      *   /                 S = Change sign             │",
  264.    "│                                            Q = Solve quadratic         │",
  265.    "│         1  2  3      ─┘ Enter             C = Clear all               │",
  266.    "│                                                                        │",
  267.    "│            0                             Esc = Quit                    │",
  268.    "│                                                                        │",
  269.    "└────────────────────────────────────────────────────────────────────────┘"
  270.     };
  271.     int i;
  272.  
  273.     clear_scrn( 7, 0, 24 );
  274.     if( vconfig.display )
  275.     ClearBox( 31, 6, 2, 21, 77 );
  276.     else
  277.     ClearBox( 15, 6, 2, 21, 77 );
  278.     ClearBox( 7, 9, 14, 9, 29 );        /* Clear entry window  */
  279.     ClearBox( 7, 9, 49, 10, 66 );        /* Clear result window */
  280.     for( i = 0; i < 19; i++)            /* Display calculator  */
  281.     StrWrite( i + 3, 3, calculator[i] );
  282. }
  283.  
  284.  
  285.  
  286. /* display_help - Clears screen and displays help text.
  287.  *
  288.  * Params:  None
  289.  */
  290.  
  291. void display_help( void )
  292. {
  293.     static char *help_msg[23] =
  294.     {
  295.     "The Integer Calculator works somewhat like a Hewlett-Packard hand " \
  296.     "calculator.", "Type the first integer, press Enter (─┘), type the " \
  297.     "second integer, and press", "the desired operator key.  The answer " \
  298.     "appears in the result window.",
  299.     "",
  300.     "To keep things simple, the Integer Calculator handles only long or " \
  301.     "short", "integers -- no floating point numbers allowed.  Unsigned " \
  302.     "numbers can range", "from 0 to 4,294,967,295; signed numbers from " \
  303.     "-2,147,483,648 to 2,147,483,647.", "There's one exception to " \
  304.     "this:  when dividing two numbers, the divisor must", "be a short " \
  305.     "integer from 0 to 65,535 for unsigned division, or from -32,768",
  306.     "to 32,767 for signed division.",
  307.     "",
  308.     "Press the M key to toggle between signed and unsigned arithmetic.  " \
  309.     "Press the", "S key to change the sign of the number in the entry " \
  310.     "window.  You'll notice", "the Calculator allows a change of sign " \
  311.     "only in \"signed\" mode.",
  312.     "",
  313.     "The Calculator uses coprocessor instructions (either real or " \
  314.     "simulated) to", "solve for the roots of a quadratic equation in " \
  315.     "the form",
  316.     "",
  317.     "                     A*x*x + B*x + C = 0",
  318.     "",
  319.     "Enter the three equation constants A, B, and C in order, then " \
  320.     "press Q.  The", "roots, if they exist, appear in the result " \
  321.     "window.  If the equation has only", "one root, then only a single " \
  322.     "number is displayed."
  323.     };
  324.     int i;
  325.  
  326.     clear_scrn( 7, 0, 24 );
  327.     for( i = 0; i < 23; i++)
  328.     StrWrite( i, 0, help_msg[i] );
  329.     press();
  330. }
  331.  
  332.  
  333. /* push - Pushes values down one stack position:  s3 becomes s2,
  334.  * s2 becomes s1, and s1 becomes the value in the entry window.
  335.  *
  336.  * Params:  sign - Current sign status (0 = positive, 1 = negative)
  337.  */
  338.  
  339. void push( int sign )
  340. {
  341.     unsigned long place;
  342.  
  343.     s3      = s2;
  344.     s2      = s1;
  345.     s1      = 0;
  346.     place = 1;
  347.     if( entry[col - 20] )
  348.     {
  349.     s1    = (long) (entry[col - 20] - '0');
  350.     place = 10;
  351.     }
  352.     while( col > 20 )
  353.     {
  354.     s1    += place * (long) (entry[--col - 20] - '0');
  355.     place *= 10;
  356.     }
  357.     if( sign )
  358.     s1 = -s1;
  359.     ClearBox( 7, 9, 15, 9, 29 );    /* Clear entry window         */
  360.     entry[0] = 0;            /* Reinitialize entry string */
  361.     col      = 20;            /* Reset column count         */
  362. }
  363.  
  364.  
  365. /* press - Prompt for keyboard signal to continue.
  366.  *
  367.  * Params:  None
  368.  */
  369.  
  370. void press( void )
  371. {
  372.     SetCurPos( 24, 49 );
  373.     printf( ". . . press a key to continue" );
  374.     SetCurPos( 24, 47 );
  375.     getch();
  376. }
  377.