• R/O
  • HTTP
  • SSH
  • HTTPS

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

This is for exploring and demonstrating ways to extend the available integer math in C. Cコンパイラが提供する整数を拡張するための探険用のソースコードです。


File Info

Rev. 056c8c9d381867aa3d96bcf05e9a165e42771547
Size 4,666 bytes
Time 2013-07-29 11:34:41
Author Joel Matthew Rees
Log Message

Where I ran out of time last week. Demonstrats add/sub/mul/bitdiv.
C's lack of an overflow target for math (especially division) makes it hard to expand.
But division is hard anyway, and the carry/overflow for the rest really is not that bad.

Content

/* Subtraction tester for an eight-bit framework 
// for testing various arithmetic techniques.
// Written by Joel Matthew Rees
// Copyright 2013, Joel Matthew Rees
// Distribution and use permitted under terms of the GPL v. 3,
// See the included file, LICENSE.TXT,
// or on-line at <http://www.gnu.org/licenses/>. 
*/


#include <stdio.h>

#include "nibBit.h"


int main( int argc, char * argv[] )
{  unsigned long i, j;
   long badB = 0;
   long badS = 0;
   long rangeMissB = 0;
   long rangeMissS = 0;
   long dividendlimit = 0xffff;
   long dividendstart = 0;
   long divisorlimit = 0xff;
   long divisorstart = 1;
   unsigned long countChecked = 0;

   if ( argc > 3 )
   {  char * scan;
      int i;
      for ( i = 1; i < argc; ++i )
      {  switch ( argv[ i ][ 0 ] )
         {
         case 'N': dividendlimit = strtoul( argv[ i ] + 1, &scan, 0 );
            break;
         case 'n': dividendstart = strtoul( argv[ i ] + 1, &scan, 0 );
            break;
         case 'D': divisorlimit = strtoul( argv[ i ] + 1, &scan, 0 );
            break;
         case 'd': divisorstart = strtoul( argv[ i ] + 1, &scan, 0 );
            break;
         }
         if ( divisorstart < 1 ) 
         {  divisorstart = 1;
         }
      }
/*
printf( "dividend start, limit: %lx, %lx -- divisor start, limit: %lx %lx\n",
        dividendstart, dividendlimit, divisorstart, divisorlimit );
return -1;
*/
   }
   else if ( argc > 2 )
   {  char * scan;
      dividendstart = strtoul( argv[ 1 ], &scan, 0 );
      dividendlimit = strtoul( argv[ 2 ], &scan, 0 );
   }
   else if ( argc > 1 )
   {  char * scan;
      dividendlimit = strtoul( argv[ 1 ], &scan, 0 );
   }


   initMyStack();

   for ( i = dividendstart; i <= dividendlimit; ++i )
   {  /* no divide by zero */
      for ( j = divisorstart; j <= divisorlimit; ++j )
      {  unsigned q = i / j;
         unsigned r = i % j;
         unsigned sq, sr, bq, br;
         ++countChecked;
         ( * --mySP ) = (uchar_t) i;
         ( * --mySP ) = (uchar_t) ( i >> CHAR_BIT );
         ( * --mySP ) = (uchar_t) j;
         nibBUDiv();
         bq = ( * mySP++ );
         br = ( * mySP++ );
         ( * --mySP ) = (uchar_t) i;
         ( * --mySP ) = (uchar_t) ( i >> CHAR_BIT );
         ( * --mySP ) = (uchar_t) j;
         nibUDiv();
#if defined TESTUDIVHIGHWORD
         sq = ( * mySP++ ) << BYTEBITS;
         sq |= ( * mySP++ );
#else /* !defined TESTUDIVHIGHWORD */
         sq = ( * mySP++ );
#endif /* defined TESTUDIVHIGHWORD */
         sr = ( * mySP++ );
         if ( ( q != sq ) || ( r != sr ) ) 
         {  if ( q > 0xff )
            {  rangeMissS += 1;
               printf( "out-of-range synthetic (%ld): \n", rangeMissS );

               printf( "%ld / %ld = %d r %d => bin: %d r %d | synth: %d r %d\n",
                       i, j, q, r, bq, br, sq, sr );
               printf( "0x%05lx / 0x%03lx = 0x%05x r 0x%03x => bin: 0x%05x r 0x%03x | synth: : 0x%05x r 0x%03x\n",
                       i, j, q, r, bq, br, sq, sr );
            }
            else
            {
               badS += 1;
               printf( "*** bad synthetic (%ld): \n", badS );
               printf( "%ld / %ld = %d r %d => bin: %d r %d | synth: %d r %d\n",
                       i, j, q, r, bq, br, sq, sr );
               printf( "0x%05lx / 0x%03lx = 0x%05x r 0x%03x => bin: 0x%05x r 0x%03x | synth: : 0x%05x r 0x%03x\n",
                       i, j, q, r, bq, br, sq, sr );
            }
         }
         else if ( ( q != bq ) || ( r != br ) ) 
         {  if ( q > 0xff )
            {  rangeMissB += 1;
/*
               printf( "out-of-range binary shift (%ld): \n", rangeMissB );
               printf( "%ld / %ld = %d r %d => bin: %d r %d | synth: %d r %d\n",
                       i, j, q, r, bq, br, sq, sr );
               printf( "0x%05lx / 0x%03lx = 0x%05x r 0x%03x => bin: 0x%05x r 0x%03x | synth: : 0x%05x r 0x%03x\n",
                       i, j, q, r, bq, br, sq, sr );
*/
            }
            else
            {
               badB += 1;
               printf( "*** bad binary shift (%ld): ", badB );
               printf( "%ld / %ld = %d r %d => bin: %d r %d | synth: %d r %d\n",
                       i, j, q, r, bq, br, sq, sr );
               printf( "0x%05lx / 0x%03lx = 0x%05x r 0x%03x => bin: 0x%05x r 0x%03x | synth: : 0x%05x r 0x%03x\n",
                       i, j, q, r, bq, br, sq, sr );
            }
         }
      }
      printf( "i: %04lx -- Range miss bin: %ld, synth: %ld out of %ld\n", 
              i, rangeMissB, rangeMissS, countChecked );
      printf( "Bad counts -- binary: %ld, synthetic: %ld\n", badB, badS );
   }

   return badB | badS;
}