//================================================================================================== // S t a n d a r d Interface // M a t h s // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library 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 Library General Public License for more details (http://www.gnu.org).
/*DESCRIPTION*/ /* This module provides common mathematical facilities. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "standard/maths.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guStandardMaths #define guStandardMaths
// Headers //--------------------------------------------------------------------------------------- #include <cmath> /*INCLUDE*/ #include <cstdlib> /*INCLUDE*/ #include <bpp/standard/conversion.hpp> /*INCLUDE*/ #include <bpp/standard/string.hpp> /*INCLUDE*/
namespace bpp {
// Importation/Exportation //----------------------------------------------------------------------- #ifdef STANDARD_DLL #define dll_export DLL_EXPORT #else #define dll_export DLL_IMPORT #endif
// Namespaces //------------------------------------------------------------------------------------ #define public_area standardMaths #define private_area standardMaths_private
namespace public_area { /*NAMESPACE*/ using namespace standardConversion; /*NAMESPACE*/ using namespace standardString; }
namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniStandardMaths has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- #undef log2
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //-----------------------------------------------------------------------------------Variable Types /*TYPE*/ /* Symbolic constants for element comparison. */ enumeration { equal, inferior, superior } tyComparison;
/*TYPE*/ /* A mark on an element. */ typedef tyInteger tyMark; //-----------------------------------------------------------------------------------Constant Types typedef const tyComparison tcComparison; typedef const tyMark tcMark; }
namespace private_area {}
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { template <class prType> const prType & maxi(const prType &,const prType &); template <class prType> const prType & mini(const prType &,const prType &); template <class prType> void swap(prType &,prType &);
inline tyBoolean isEqual(tyReal,tyReal); inline tyBoolean isInferior(tyReal,tyReal); inline tyBoolean isInferiorEqual(tyReal,tyReal); inline tyBoolean isSuperior(tyReal,tyReal); inline tyBoolean isSuperiorEqual(tyReal,tyReal);
function tyReal ceiling(tyReal); inline tyReal floor(tyReal);
inline tyBoolean addOk(tyCardinal,tyCardinal); inline tyBoolean addOk(tyInteger,tyInteger); inline tyBoolean mulOk(tyCardinal,tyCardinal); inline tyBoolean mulOk(tyInteger,tyInteger); inline tyBoolean subOk(tyCardinal,tyCardinal); inline tyBoolean subOk(tyInteger,tyInteger);
function tyCardinal bottomDiv(tyCardinal,tyCardinal); function tyInteger bottomDiv(tyInteger,tyInteger); function tyCardinal topDiv(tyCardinal,tyCardinal); function tyInteger topDiv(tyInteger,tyInteger);
function tyInteger percentage(tyInteger,tyCardinal); function tyCardinal percentage(tyCardinal,tyCardinal);
inline tyInteger modSign(tyInteger); inline tyInteger sign(tyInteger); inline tyBoolean exor(tyBoolean,tyBoolean);
inline tyReal log10(tyReal); inline tyReal log2(tyReal); inline tyReal power10(tyReal); inline tyReal power2(tyReal);
inline clString string(tyBoolean); inline clString string(tyByte); inline clString string(tyCardinal); inline clString string(tyCharacter); inline clString string(tyInteger); inline clString string(tyPointer); inline clString string(tyReal);
function tyBoolean boolean(tcString); inline tyByte byte(tcString); function tyCardinal cardinal(tcString); inline tyCharacter character(tcString); function tyComparison comparison(tcString); function tyInteger integer(tcString); function tyPointer pointer(tcString); function tyReal real(tcString);
inline clString comparisonToString(tyComparison); }
namespace private_area { testing_mode ( function void test(void); ) }
// Errors //---------------------------------------------------------------------------------------- namespace public_area { /*ERROR*/ extern_error erCardinalOverflow; /* The coding of cardinals is too small. */ /*ERROR*/ extern_error erEpsilonParameterMissing; /* The 'epsilon' parameter is missing. */ /*ERROR*/ extern_error erIntegerOverflow; /* The coding of integers is too small. */ /*ERROR*/ extern_error erInvalidBooleanString; /* Invalid boolean string. */ /*ERROR*/ extern_error erInvalidCardinalString; /* Invalid cardinal string. */ /*ERROR*/ extern_error erInvalidCharacterString; /* Invalid character string. */ /*ERROR*/ extern_error erInvalidComparisonString; /* Invalid comparison string. */ /*ERROR*/ extern_error erInvalidIntegerString; /* Invalid integer string. */ /*ERROR*/ extern_error erInvalidPercentage; /* The percentage is over a hundred. */ /*ERROR*/ extern_error erInvalidPointerString; /* Invalid pointer string. */ /*ERROR*/ extern_error erInvalidRealString; /* Invalid real string. */ /*ERROR*/ extern_error erZeroDivision; /* Can not perform a division by zero. */ }
// Constants & Variables //------------------------------------------------------------------------- /*CONSTANT*/ /* Maximum positive real number that is considered to be equal to zero. We call it the standard precision. It is the precision of the real numbers that is considered by the functions provided in this library. */ extern_static_constant(public,tyReal,goEpsilon,epsilon);
/*CONSTANT*/ /* First element mark. */ extern_static_constant(public,tyMark,goFirstMark,firstMark);
/*CONSTANT*/ /* Last element mark. */ extern_static_constant(public,tyMark,goLastMark,lastMark);
// Functions Inline //------------------------------------------------------------------------------ namespace public_area { //---------------------------------------------------------------------------------------------Maxi /*FUNCTION*/ /* Returns the maximum of two objects. */ template <class prType> inline const prType & maxi(const prType & agObject1,const prType & agObject2) { if (agObject1>=agObject2) return (agObject1); return (agObject2); } //---------------------------------------------------------------------------------------------Mini /*FUNCTION*/ /* Returns the minimum of two objects. */ template <class prType> inline const prType & mini(const prType & agObject1,const prType & agObject2) { if (agObject1<=agObject2) return (agObject1); return (agObject2); } //---------------------------------------------------------------------------------------------Swap /*FUNCTION*/ /* Swaps two objects. */ template <class prType> inline void swap(prType & agObject1,prType & agObject2) { prType lcTempo = agObject1;
agObject1=agObject2; agObject2=lcTempo; }
//------------------------------------------------------------------------------------------IsEqual /*FUNCTION*/ /* Indicates if two real numbers are equal according to the standard precision. */ inline tyBoolean isEqual(tyReal agNumber1,tyReal agNumber2) { return ((agNumber1-agNumber2)<=epsilon() and (agNumber2-agNumber1)<=epsilon()); } //---------------------------------------------------------------------------------------IsInferior /*FUNCTION*/ /* Indicates if a real number is inferior to another one according to the standard precision. */ inline tyBoolean isInferior(tyReal agNumber1,tyReal agNumber2) { return ((agNumber2-agNumber1)>epsilon()); } //----------------------------------------------------------------------------------IsInferiorEqual /*FUNCTION*/ /* Indicates if a real number is inferior or equal to another one according to the standard precision. */ inline tyBoolean isInferiorEqual(tyReal agNumber1,tyReal agNumber2) { return ((agNumber1-agNumber2)<=epsilon()); } //---------------------------------------------------------------------------------------IsSuperior /*FUNCTION*/ /* Indicates if a real number is superior to another one according to the standard precision. */ inline tyBoolean isSuperior(tyReal agNumber1,tyReal agNumber2) { return ((agNumber1-agNumber2)>epsilon()); } //----------------------------------------------------------------------------------IsSuperiorEqual /*FUNCTION*/ /* Indicates if a real number is superior or equal to another one according to the standard precision. */ inline tyBoolean isSuperiorEqual(tyReal agNumber1,tyReal agNumber2) { return ((agNumber2-agNumber1)<=epsilon()); }
//--------------------------------------------------------------------------------------------Floor /*FUNCTION*/ /* Returns the maximum integer value inferior or equal to a given real value according to the standard precision. */ inline tyReal floor(tyReal agNumber) { tyReal lcFractional; tyReal lcIntegral;
if (agNumber<0.0) return (-standardMaths::ceiling(-agNumber)); else { lcFractional=std::modf(agNumber,&lcIntegral); if (isEqual(lcFractional,1.0)) lcIntegral+=1.0; return (lcIntegral); } }
//--------------------------------------------------------------------------------------------AddOk /*FUNCTION*/ /* Checks if the addition of two cardinals will not fail. */ inline tyBoolean addOk(tyCardinal agNumber1,tyCardinal agNumber2) { return (cardinalMax()-agNumber1 >= agNumber2); } //--------------------------------------------------------------------------------------------AddOk /*FUNCTION*/ /* Checks if the addition of two integers will not fail. */ inline tyBoolean addOk(tyInteger agNumber1,tyInteger agNumber2) { if (agNumber2>=0) return (agNumber1 <= integerMax()-agNumber2); return (agNumber1 >= integerMin()-agNumber2); } //--------------------------------------------------------------------------------------------MulOk /*FUNCTION*/ /* Checks if the multiplication of two cardinals will not fail. */ inline tyBoolean mulOk(tyCardinal agNumber1,tyCardinal agNumber2) { if (agNumber2==0) return (true); return (cardinalMax()/agNumber2 >= agNumber1); } //--------------------------------------------------------------------------------------------MulOk /*FUNCTION*/ /* Checks if the multiplication of two integers will not fail. */ inline tyBoolean mulOk(tyInteger agNumber1,tyInteger agNumber2) { if (agNumber2==0) return (true);
if (agNumber2>0) return ((agNumber1 <= integerMax()/agNumber2) and (agNumber1 >= integerMin()/agNumber2));
if (agNumber2==-1) return (agNumber1>=-integerMax()); return ((agNumber1 >= integerMax()/agNumber2) and (agNumber1 <= integerMin()/agNumber2)); } //--------------------------------------------------------------------------------------------SubOk /*FUNCTION*/ /* Checks if the subtraction of two cardinals will not fail. */ inline tyBoolean subOk(tyCardinal agNumber1,tyCardinal agNumber2) { return (agNumber1>=agNumber2); } //--------------------------------------------------------------------------------------------SubOk /*FUNCTION*/ /* Checks if the subtraction of two integers will not fail. */ inline tyBoolean subOk(tyInteger agNumber1,tyInteger agNumber2) { if (agNumber2>=0) return (agNumber1 >= integerMin()+agNumber2); return (agNumber1 <= integerMax()+agNumber2); }
//------------------------------------------------------------------------------------------ModSign /*FUNCTION*/ /* Returns the sign of the modulo operator upon a given integer. */ inline tyInteger modSign(tyInteger agInteger) { if (agInteger<0) return ((-1)%2); else return (1); } //---------------------------------------------------------------------------------------------Sign /*FUNCTION*/ /* Returns the sign of an integer. */ inline tyInteger sign(tyInteger agInteger) { if (agInteger<0) return (-1); else return (1); } //----------------------------------------------------------------------------------------------Xor /*FUNCTION*/ /* Returns the result of the XOR operator upon two boolean expressions. */ inline tyBoolean exor(tyBoolean agExpression1,tyBoolean agExpression2) { return ((agExpression1 and not agExpression2) or (not agExpression1 and agExpression2)); }
//--------------------------------------------------------------------------------------------Log10 /*FUNCTION*/ /* Returns the natural logarithm of a number to the base 10. */ inline tyReal log10(tyReal agNumber) { return (std::log(agNumber)/std::log(tyReal(10.0))); } //---------------------------------------------------------------------------------------------Log2 /*FUNCTION*/ /* Returns the natural logarithm of a number to the base 2. */ inline tyReal log2(tyReal agNumber) { return (std::log(agNumber)/std::log(tyReal(2.0))); } //------------------------------------------------------------------------------------------Power10 /*FUNCTION*/ /* Returns 10 raised to a given exponent. */ inline tyReal power10(tyReal agExponent) { return (std::pow(tyReal(10.0),agExponent)); } //-------------------------------------------------------------------------------------------Power2 /*FUNCTION*/ /* Returns 2 raised to a given exponent. */ inline tyReal power2(tyReal agExponent) { return (std::pow(tyReal(2.0),agExponent)); }
//--------------------------------------------------------------------------------Boolean To String /*FUNCTION*/ /* Converts a boolean into a string. */ inline clString string(tyBoolean agBoolean) { if (agBoolean) return (clString("yes")); return (clString("no")); } //-------------------------------------------------------------------------------Cardinal To String /*FUNCTION*/ /* Converts a cardinal into a string. */ inline clString string(tyCardinal agCardinal) { tyCharacter lcString[64];
bpp::low::string::toString(lcString,agCardinal); return (clString(lcString)); } //-----------------------------------------------------------------------------------Byte To String /*FUNCTION*/ /* Converts a byte into a string. */ inline clString string(tyByte agByte) { return (string(standardConversion::cardinal(agByte))); } //------------------------------------------------------------------------------Character To String /*FUNCTION*/ /* Converts a character into a string. */ inline clString string(tyCharacter agCharacter) { tyCharacter lcString[2];
lcString[0]=agCharacter; lcString[1]=end_string; return (clString(lcString)); } //--------------------------------------------------------------------------------Integer To String /*FUNCTION*/ /* Converts an integer into a string. */ inline clString string(tyInteger agInteger) { tyCharacter lcString[64];
bpp::low::string::toString(lcString,agInteger); return (clString(lcString)); } //--------------------------------------------------------------------------------Pointer To String /*FUNCTION*/ /* Converts a pointer into a string. */ inline clString string(tyPointer agPointer) { tyCharacter lcString[64];
bpp::low::string::toString(lcString,agPointer); return (clString(lcString)); } //-----------------------------------------------------------------------------------Real To String /*FUNCTION*/ /* Converts a real into a string. */ inline clString string(tyReal agReal) { tyCharacter lcString[64];
bpp::low::string::toString(lcString,agReal); return (clString(lcString)); } //-----------------------------------------------------------------------------------String To Byte /*FUNCTION*/ /* Converts a string into a byte. */ inline tyByte byte(tcString agString) { return (standardConversion::byte(cardinal(agString))); } //------------------------------------------------------------------------------String To Character /*FUNCTION*/ /* Converts a string into a character. */ inline tyCharacter character(tcString agString) { if (agString==nil) send_inline_error(erInvalidCharacterString,"character"); return (agString[0]); } //-----------------------------------------------------------------------------Comparison To String /*FUNCTION*/ /* Converts an element comparison into a string. */ inline clString comparisonToString(tyComparison agComparison) { if (agComparison==standardMaths::equal) return (clString("=")); if (agComparison==standardMaths::inferior) return (clString("<")); return (clString(">")); } }
namespace private_area {}
// X X X Inline //--------------------------------------------------------------------------------- namespace {}
// End //------------------------------------------------------------------------------------------- } #undef dll_export #undef private_area #undef public_area #endif |
//================================================================================================== // S t a n d a r d Implementation // M a t h s // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library 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 Library General Public License for more details (http://www.gnu.org).
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "standard/maths.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define STANDARD_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/standard/maths.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area standardMaths #define private_area standardMaths_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Standard/Maths");
// Initialization //-------------------------------------------------------------------------------- #undef iniStandardMaths static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area { static_error erCardinalOverflow; static_error erEpsilonParameterMissing; static_error erIntegerOverflow; static_error erInvalidBooleanString; static_error erInvalidCardinalString; static_error erInvalidCharacterString; static_error erInvalidComparisonString; static_error erInvalidIntegerString; static_error erInvalidPercentage; static_error erInvalidPointerString; static_error erInvalidRealString; static_error erZeroDivision; }
// Constants & Variables //------------------------------------------------------------------------- static_constant(tyReal,goEpsilon); static_constant(tyMark,goFirstMark); static_constant(tyMark,goLastMark);
// Static Members //-------------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------------------------------Ceiling /*FUNCTION*/ /* Returns the minimum integer value superior or equal to a given real value according to the standard precision. */ function tyReal ceiling(tyReal agNumber) { tyReal lcFractional; tyReal lcIntegral;
if (agNumber<0.0) return (-standardMaths::floor(-agNumber)); else { lcFractional=std::modf(agNumber,&lcIntegral); if (isSuperior(lcFractional,0.0)) lcIntegral+=1.0; return (lcIntegral); } } //----------------------------------------------------------------------------------------BottomDiv /*FUNCTION*/ /* Returns the truncated division of two cardinals. The returned value is the cardinal just below or equal to the division. */ function tyCardinal bottomDiv(tyCardinal agDividend,tyCardinal agDivisor) { method_name("bottomDiv");
if (agDivisor==0) send_error(erZeroDivision); return (agDividend/agDivisor); } //----------------------------------------------------------------------------------------BottomDiv /*FUNCTION*/ /* Returns the truncated division of two integers. The returned value is the integer just below or equal to the division. */ function tyInteger bottomDiv(tyInteger agDividend,tyInteger agDivisor) { method_name("bottomDiv");
if (agDivisor==0) send_error(erZeroDivision); if (agDividend%agDivisor == 0) return (agDividend/agDivisor); if (exor(agDividend>0,agDivisor>0)) return (agDividend/agDivisor - 1); return (agDividend/agDivisor); } //-------------------------------------------------------------------------------------------TopDiv /*FUNCTION*/ /* Returns the truncated division of two cardinals. The returned value is the cardinal just above or equal to the division. */ function tyCardinal topDiv(tyCardinal agDividend,tyCardinal agDivisor) { method_name("topDiv");
if (agDivisor==0) send_error(erZeroDivision); if (agDividend%agDivisor == 0) return (agDividend/agDivisor); return (agDividend/agDivisor + 1); } //-------------------------------------------------------------------------------------------TopDiv /*FUNCTION*/ /* Returns the truncated division of two integers. The returned value is the integer just above or equal to the division. */ function tyInteger topDiv(tyInteger agDividend,tyInteger agDivisor) { method_name("topDiv");
if (agDivisor==0) send_error(erZeroDivision); if (agDividend%agDivisor == 0) return (agDividend/agDivisor); if (exor(agDividend>0,agDivisor>0)) return (agDividend/agDivisor); return (agDividend/agDivisor + 1); } //---------------------------------------------------------------------------------------Percentage /*FUNCTION*/ /* Returns a given percentage of a cardinal value. */ function tyCardinal percentage(tyCardinal agNumber,tyCardinal agPercentage) { method_name("percentage");
if (agPercentage>100) send_error(erInvalidPercentage); return ((agNumber/100u)*agPercentage + ((agNumber%100u)*agPercentage)/100u); } //---------------------------------------------------------------------------------------Percentage /*FUNCTION*/ /* Returns a given percentage of an integer value. */ function tyInteger percentage(tyInteger agNumber,tyCardinal agPercentage) { method_name("percentage");
if (agPercentage>100) send_error(erInvalidPercentage);
return ((agNumber/100l)*tyInteger(agPercentage) + sign(agNumber)*modSign(agNumber)*(((agNumber%100l)*tyInteger(agPercentage))/100l)); } //--------------------------------------------------------------------------------String To Boolean /*FUNCTION*/ /* Converts a string into a boolean. */ function tyBoolean boolean(tcString agString) { method_name("boolean");
if (compare(agString,"yes")==0 or compare(agString,"true")==0) return (true); if (compare(agString,"no")==0 or compare(agString,"false")==0) return (false); send_error(erInvalidBooleanString); return (false); } //-------------------------------------------------------------------------------String To Cardinal /*FUNCTION*/ /* Converts a string into a cardinal. */ function tyCardinal cardinal(tcString agString) { method_name("cardinal");
tyCardinal lcCardinal;
if (agString==nil) send_error(erInvalidCardinalString); if (bpp::low::string::toCardinal(agString,lcCardinal)==nil) send_error(erInvalidCardinalString); return (lcCardinal); } //-----------------------------------------------------------------------------String To Comparison /*FUNCTION*/ /* Converts a string into an element comparison. */ function tyComparison comparison(tcString agString) { method_name("comparison");
if (compare(agString,"=")==0) return (public_area::equal); if (compare(agString,"<")==0) return (inferior); if (compare(agString,">")==0) return (superior); send_error(erInvalidComparisonString); return (public_area::equal); } //--------------------------------------------------------------------------------String To Integer /*FUNCTION*/ /* Converts a string into an integer. */ function tyInteger integer(tcString agString) { method_name("integer");
tyInteger lcInteger;
if (agString==nil) send_error(erInvalidIntegerString); if (bpp::low::string::toInteger(agString,lcInteger)==nil) send_error(erInvalidIntegerString); return (lcInteger); } //--------------------------------------------------------------------------------String To Pointer /*FUNCTION*/ /* Converts a string into a pointer. */ function tyPointer pointer(tcString agString) { method_name("pointer");
tyPointer lcPointer;
if (agString==nil) send_error(erInvalidPointerString); if (bpp::low::string::toPointer(agString,lcPointer)==nil) send_error(erInvalidPointerString); return (lcPointer); } //-----------------------------------------------------------------------------------String To Real /*FUNCTION*/ /* Converts a string into a real. */ function tyReal real(tcString agString) { method_name("real");
tyReal lcReal;
if (agString==nil) send_error(erInvalidRealString); if (bpp::low::string::toReal(agString,lcReal)==nil) send_error(erInvalidRealString); return (lcReal); } }
namespace private_area {}
// I n i t i a l i z e r Implementation //--------------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------------Start property void clInitializer::start(void) { if (atCounter++ == 0) { try { #include <bpp/modules.hpp> /*NEED*/ registerStop(this); environment::informInitialization(goModuleName);
method_name("initializer::constructor");
erCardinalOverflow.create("The coding of cardinals is too small."); erEpsilonParameterMissing.create("The 'epsilon' parameter is missing."); erIntegerOverflow.create("The coding of integers is too small."); erInvalidBooleanString.create("Invalid boolean string."); erInvalidCardinalString.create("Invalid cardinal string."); erInvalidCharacterString.create("Invalid character string."); erInvalidComparisonString.create("Invalid comparison string."); erInvalidIntegerString.create("Invalid integer string."); erInvalidPercentage.create("The percentage is over a hundred."); erInvalidPointerString.create("Invalid pointer string."); erInvalidRealString.create("Invalid real string."); erZeroDivision.create("Can't perform a division by zero.");
goFirstMark = integerMin(); goLastMark = integerMax();
if (environment::parameters().count(clString("epsilon"))==0) send_error(erEpsilonParameterMissing);
goEpsilon = real(environment::parameter(clString("epsilon")).data()); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { environment::informTermination(goModuleName); } }
// End //------------------------------------------------------------------------------------------- } |
|