/*============================================================================== | | NAME | | Primpoly.cpp | | DESCRIPTION | | Compute primitive polynomials of degree n modulo p. | | CALLING SEQUENCE | | main() is called by the OS. | | LEGAL | | Primpoly Version 9.1 - A Program for Computing Primitive Polynomials. | Copyright (C) 1999-2008 by Sean Erik O'Connor. All Rights Reserved. | | This program is free software; you can redistribute it and/or modify it | under the terms of the GNU General Public License as published by the Free | Software Foundation; version 2 of the License. | | This program is distributed in the hope that it will be useful, but | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | for more details. | | You should have received a copy of the GNU General Public License along | with this program; if not, write to the Free Software Foundation, Inc., 59 | Temple Place - Suite 330, Boston, MA 02111-1307, USA. | | The author's address is artifex@seanerikoconnor.freeservers.com. | ==============================================================================*/ /*------------------------------------------------------------------------------ | Include Files | ------------------------------------------------------------------------------*/ #include // abort() #include // Basic stream I/O. #include // set_new_handler() #include // Basic math functions e.g. sqrt() #include // Numeric limits. #include // Complex data type and operations. #include // File stream I/O. #include // String stream I/O. #include // STL vector class. #include // STL string class. #include // Iterators. #include // Exceptions. #include // assert() #ifdef _MSC_VER #include // new_handler() #endif using namespace std ; // So we don't need to use the std:: prefix everywhere. #include "ctype.h" // C string functions. /*------------------------------------------------------------------------------ | PP Include Files | ------------------------------------------------------------------------------*/ #include "Primpoly.h" // Global functions. #include "ppArith.h" // Basic arithmetic functions. #include "ppBigInt.h" // Arbitrary precision integer arithmetic. #include "ppStatistics.h" // Statistics collection for factoring and poly finding. #include "ppFactor.h" // Prime factorization and Euler Phi. #include "ppParser.h" // Parsing of polynomials and I/O services. #include "ppPolynomial.h" // Polynomial operations and mod polynomial operations. #include "ppUnitTest.h" // Complete unit test. /*------------------------------------------------------------------------------ | Remap new and unexpected handlers | ------------------------------------------------------------------------------*/ // Patch Microsoft VC++ so new() throws bad_alloc. #ifdef _MSC_VER int MyNewHandler( size_t size ) { cout << "Throwing bad_alloc() exception from the new handler" << endl ; throw bad_alloc() ; return 0 ; // Allocation failed. } #endif // _MSC_VER // Violating an exception specification (throwing a type of exception // from within a function which does not match its exception specification) // normally causes a call to unexpected() which calls terminate() which // in turn calls abort(). // // We don't want to abruptly stop like this, so // we remap unexpected() so that it throws the exception "bad_exception". // // The drawback is that now all functions need to include bad_exception in // their exception specifications list. void MyUnexpectedHandler() { cout << "Throwing runtime_error() exception " "from the unexpected() handler" << endl ; throw bad_exception() ; return ; } /*============================================================================= | | NAME | | main | | DESCRIPTION | | Program for finding a primitive polynomial of degree n modulo p for use | in generating PN sequences and finite fields for error control coding. | | CALLING SEQUENCE | | Run the program by typing | | $ Primpoly p n | | You will get an nth degree primitive polynomial modulo p. | | User manual and technical documentation are described in detail in my web page at | http://seanerikoconnor.freeservers.com/Mathematics/AbstractAlgebra/PrimitivePolynomials/overview.html | +============================================================================*/ int main( int argc, char * argv[] ) { // If an exception specification is violated, instead of aborting, // convert to throw bad_exception. set_unexpected( MyUnexpectedHandler ) ; // Patch Microsoft VC++ so new() throws bad_alloc. #ifdef _MSC_VER _set_new_handler( MyNewHandler ) ; #endif try { // Show the legal notice first. cout << legalNotice ; // Do a self check first, always. bool unitTestStatus = unitTest() ; if (!unitTestStatus) throw PrimpolyError( "Self-check failed!" ) ; else cout << "Self-check passes..." << endl ; // Read the parameters p and n from the command line. // Throw a parsing exception if there is a problem. Parser parser ; parser.parseCommandLine( argc, argv ) ; // Did user ask for help? if (parser.printHelp) { cout << helpText ; return AskForHelp ; } // Test a polynomial which is input by the user for primitivity. if (parser.testPolynomialForPrimitivity) { // Error check inputs. Polynomial f( parser.testPolynomial ) ; if (f.deg() < minDegree) { ostringstream os ; os << "Error. Polynomial degree must be >= " << minDegree << endl ; throw PolynomialRangeError( os.str() ) ; } else if (f.modulus() < minModulus || !is_almost_surely_prime( static_cast( f.modulus()) )) { ostringstream os ; os << "Error. Polynomial modulus must be >= " << minModulus << endl ; throw PolynomialRangeError( os.str() ) ; } PolyOrder order( f ) ; if (order.isPrimitive()) cout << f << " is primitive!" << endl ; else cout << f << " is NOT primitive!" << endl ; if (parser.printStatistics) order.statistics_.print() ; return Success ; } // Check to see if p is a prime. if (!is_almost_surely_prime( static_cast( parser.p ))) throw ParserError( "ERROR: p must be a prime number.\n\n" ) ; // Find a primitive polynomial. findPrimitivePolynomial( parser.p, parser.n, parser.printStatistics ) ; return Success ; } // Catch all exceptions and report what happened to the user. // First do the user-defined exceptions. catch( PrimpolyError & e ) { cerr << "Error: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch( ParserError & e ) { cerr << "Inputs are incorrect or out of range: " << e.what() << endl ; cerr << helpText ; return RangeError ; } catch ( BigIntRangeError & e ) { cerr << "Internal range error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( BigIntDomainError & e ) { cerr << "Internal domain error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( BigIntUnderflow & e ) { cerr << "Internal underflow error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( BigIntOverflow & e ) { cerr << "Internal overflow error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( BigIntZeroDivide & e ) { cerr << "Internal zero divide error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( BigIntMathError & e ) { cerr << "Internal math error in multiple precision arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( ArithModPException & e ) { cerr << "Internal modulo p arithmetic error: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch (PolynomialRangeError & e) { cout << "Error. Polynomial has bad syntax or coefficients are out of range. " << e.what() << endl ; return RangeError ; } catch ( PolynomialError & e ) { cerr << "Error in polynomial arithmetic: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } // // Standard library exceptions. // catch ( bad_alloc & e ) { cerr << "Error allocating memory: " << e.what() << endl ; cerr << "Try again with smaller p and n" << endl ; cerr << "or try on a computer with more RAM or virtual memory." << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch ( bad_exception & e ) { cerr << "Bad exception violation: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } catch( exception & e ) { cerr << "Standard library error: " << e.what() << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } // Catch all other uncaught exceptions, which would otherwise call terminate() // which in turn calls abort() and which would halt this program. // // Limitations: // We can't handle the case where terminate() gets called because the // exception mechanism finds a corrupt stack or catches a destructor // throwing an exception. // // Also we can't catch exceptions which are thrown by initializing or // destructing global variables. catch( ... ) { cerr << "Unexpected exception: " << endl ; cerr << writeToAuthorMessage << endl ; return InternalError ; } return Success ; } //========================== end of function main ========================