#include "options.h" #include "config.h" #include "unitnumber.h" #include "unitparser.h" #include "number.h" #include "lexer.h" #include "parser.h" #include #include #include Options::Options( int argc, char *argv[] ) : iScale( 0 ), iRadix( 10 ) { addOption( iRadix, 'r', "radix", Bu::String("Set the radix (default: %1)").arg( iRadix ) ); addOption( iScale, 's', "scale", Bu::String("Set the scale (default: %1)").arg( iScale ) ); addOption( Bu::slot(this, &Options::selfTest), "self-test", "Run a series of tests to ensure everything is working correctly."); addOption( Bu::slot(this, &Options::textPrimes), "text-primes", "Generate primes in base 36 that only have digits > 9 in them. " "Yes, this is entirely silly and purely for entertainment."); addOption( Bu::slot(this, &Options::isPrime), 'p', "is-prime", "Tests every parameter after to see if it is prime then prints out " "the ones that are prime. Set radix first."); addOption( Bu::slot(this, &Options::convert), 'c', "convert", "Convert the provided number to the given radix in the format " "number:to-radix or from-radix:number:to-radix. The radix should " "be provided in base-10"); addOption( Bu::slot(this, &Options::execute), 'e', "execute", "Execute the next parameters as an equation and print the result. " "If you want a different scale or radix then set them first. This will " "use all remaining parameters as the equation (you may wish to quote " "your equation to prevent special characters from being interpreted by " "your shell)."); addOption( Bu::slot(this, &Options::sum), "sum", "Read numbers from standard input and sum them, output the result."); addOption( Bu::slot(this, &Options::grind), 'g', "grind", "Search for magic numbers. Secret magic numbers."); addOption( Bu::slot(this, &Options::version), 'v', "version", "Show the version string ('" CLIC_VERSION_STR "')"); addHelpOption('h', "help", "This help"); parse( argc, argv ); } Options::~Options() { } int Options::selfTest( Bu::StringArray ) { UnitNumber().run(); UnitParser().run(); exit( 0 ); return 0; } bool hasDigits( const Bu::String &s ) { for( Bu::String::const_iterator i = s.begin(); i; i++ ) { if( *i >= '0' && *i <= '9' ) return true; } return false; } int Options::textPrimes( Bu::StringArray aArgs ) { Number tst( 0, 36 ); Number max( 0, 36 ); Number j( 0, 36 ); Number one( 0, 36 ); Number fact( 0, 36 ); one = "1"; fact = "2"; if( aArgs.getSize() >= 2 ) tst = aArgs[1]; else tst = "1"; for(;; tst = tst + one ) { if( hasDigits( tst.toString() ) ) continue; max = tst / fact; bool bPrime = true; for( j = "2"; j < max; j = j + one ) { if( (tst%j).isZero() ) { bPrime = false; break; } } if( bPrime ) { Bu::println("%1").arg( tst ); } } exit( 0 ); return 0; } int Options::isPrime( Bu::StringArray aArgs ) { Number tst( 0, iRadix ); Number max( 0, iRadix ); Number j( 0, iRadix ); Number one( 0, iRadix ); Number fact( 0, iRadix ); one = "1"; fact = "2"; for( Bu::StringArray::iterator i = aArgs.begin()+1; i; i++ ) { tst = *i; max = tst / fact; bool bPrime = true; for( j = "2"; j < max; j = j + one ) { if( (tst%j).isZero() ) { bPrime = false; break; } } if( bPrime ) { Bu::println("%1").arg( tst ); } } exit( 0 ); return aArgs.getSize(); } int Options::convert( Bu::StringArray aArgs ) { for( Bu::StringArray::iterator i = aArgs.begin()+1; i; i++ ) { Bu::StringList lBits = (*i).split(':'); if( lBits.getSize() < 2 || lBits.getSize() > 3 ) throw Bu::ExceptionBase("Invalid format"); int iFromRadix = iRadix; int iToRadix; Number n; if( lBits.getSize() == 2 ) { iToRadix = strtol( lBits.last().getStr(), 0, 10 ); n = Number( lBits.first(), 0, iFromRadix ); } else if( lBits.getSize() == 3 ) { iFromRadix = strtol( lBits.first().getStr(), 0, 10 ); iToRadix = strtol( lBits.last().getStr(), 0, 10 ); n = Number( *(lBits.begin()+1), 0, iFromRadix ); } Bu::println("%1").arg( n.toString() ); Bu::println("%1").arg( n.toRadix( iToRadix ).toString() ); } exit( 0 ); return 0; } int Options::execute( Bu::StringArray aArgs ) { if( aArgs.getSize() == 1 ) { Bu::println("Must provide an equation to execute."); exit( 0 ); return 0; } Bu::MemBuf mbIn(aArgs[1]); mbIn.setPos( mbIn.getSize() ); for( int j = 2; j < aArgs.getSize(); j++ ) { mbIn.write(" "); mbIn.write( aArgs[j] ); } // Bu::println("eq: '''%1'''").arg( mbIn.getString() ); mbIn.setPos( 0 ); Bu::MemBuf mbOut; Lexer lex( mbIn ); lex.setScale( iScale ); lex.setRadix( iRadix ); Parser parser( lex, mbOut ); parser.parse(); Bu::print( mbOut.getString() ); exit( 0 ); return aArgs.getSize(); } int Options::sum( Bu::StringArray aArgs ) { Number sum( iScale, iRadix ); while( !Bu::sioRaw.isEos() ) { Bu::String s = Bu::sioRaw.readLine(); if( s.isEmpty() ) break; Number n( s, iScale, iRadix ); sum = sum + n; } Bu::println("%1").arg( sum ); exit( 0 ); return 0; } int Options::version( Bu::StringArray aArgs ) { Bu::println( CLIC_VERSION_STR ); exit( 0 ); return 0; } bool onlyNines( const Bu::String &s ) { for( Bu::String::const_iterator i = s.begin(); i; i++ ) { if( *i != '9' ) return false; } return true; } bool onlyOnes( const Bu::String &s ) { for( Bu::String::const_iterator i = s.begin(); i; i++ ) { if( *i != '1' ) return false; } return true; } int Options::grind( Bu::StringArray aArgs ) { Number test("1"); Number bit("1"); Number mult("2"); int64_t iBits = 1; int iLastSize = 0; if( aArgs.getSize() > 1 ) { Bu::print("Loading number..."); Bu::sioRaw.flush(); Bu::String num = Bu::File(aArgs[1], Bu::File::Read).readAll(); test = num; Bu::println("done."); Bu::print("Computing bit..."); Bu::sioRaw.flush(); bit = test; bit = bit+Number("1"); bit = bit/mult; Bu::println("done."); if( aArgs.getSize() > 2 ) { Bu::print("Trusting a human for where we are..."); Bu::sioRaw.flush(); iBits = strtoll( aArgs[2].getStr(), NULL, 10 ); } else { Bu::print("Figuring out where we are..."); Bu::sioRaw.flush(); Bu::String sBin = bit.toRadix(2).toString(); iBits = sBin.getSize(); } // Bu::println("Done. Checking."); // Bu::println("test = %1, bit = %2").arg( test ).arg( bit ); // Bu::String sTest = test.toRadix(2).toString(); // Bu::File("check-bit.txt", Bu::File::WriteNew ).write( sBin ); // Bu::File("check-test.txt", Bu::File::WriteNew ).write( sTest ); iLastSize = num.getSize(); // Bu::println("File written. %1 bits").arg( sBin.getSize() ); Bu::println("done."); Bu::println("Continuing calculation..."); } for(;;) { bit = bit*mult; test = test + bit; Bu::String r = test.toString(); iBits++; if( onlyNines(r) ) { Bu::println("%1 digits").arg( r.getSize() ); Bu::File f("answer-dec.txt", Bu::File::WriteNew ); f.write( r ); Bu::println("Success."); // Bu::println("%1 == %2").arg( test.toRadix(2) ).arg( r ); return 0; } if( r.getSize() != iLastSize && r.getSize()%1000 == 0 ) { /* Bu::String rs = test.toRadix(2).toString(); int iOBits = rs.getSize(); if( iOBits != iBits ) Bu::println("Bit mismatch: %1 vs %2").arg( iOBits ).arg( iBits ); if( !onlyOnes( rs ) ) Bu::println("Not only ones!"); */ iLastSize = r.getSize(); Bu::println("%1 digits").arg( r.getSize() ); Bu::File f(Bu::String("interum-%1-%2.txt").arg( r.getSize() ).arg( iBits ), Bu::File::WriteNew ); f.write( r ); } } Bu::println("Failure."); exit( 0 ); return 0; }