name: MScalar
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_math_scalar.a

>     #include <MScalar.h>

>     MScalar& operator+= (TIntegral arg);
>     boolean assign(byte arg);
>     TIntegral band(TIntegral arg);
>     TIntegral exp();
>     TIntegral asin();
>     TIntegral limit(TIntegral min, TIntegral max);

quick start:

>     MScalar<double, float64> val0;
>     MScalar<double, float64> val1;
>     MScalar<double, float64> min_val;

>     val0.assign((double)10);
>     (long)val0.exp2();
>     val1.exp10(2);

>     min_val.min(val0, val1);

description:
The MScalar class is the base class of all scalar classes. It includes commonly-used mathematical, logical and DSP methods, and i/o and operator overload methods. All other scalar classes are derived from it. The MScalar methods should not be used directly by users. They are designed for the other scalar classes and the MVector and MMatrix templates to use.
dependencies:

- SofParser
- String
- MemoryManager
- MScalarMethods.h

public constants:

- define the class name:

      static const String CLASS_NAME = L"MScalar";

- random number related constants:

      static const double RAND_BYTE_MAX = Integral::TWO_EXP8;

      static const double RAND_USHORT_MAX = Integral::TWO_EXP16;

      static const double RAND_ULONG_MAX = Integral::TWO_EXP32;

      static const double RAND_ULLONG_MAX = Integral::TWO_EXP64;

      static const double RAND_SHORT_MAX = Integral::TWO_EXP15;

      static const double RAND_LONG_MAX = Integral::TWO_EXP31;

      static const double RAND_LLONG_MAX = Integral::TWO_EXP63;

- i/o related constants:

      static const String DEF_PARAM = L"value";

- the default value(s) of the class data:

      static const TIntegral DEF_VALUE = (TIntegral)0.0;

- default arguments to methods:

      none

error codes:

- error code indicating MScalar class general error:

      static const long ERR = 20000;

protected data:

- the container for the value of this item:

      TIntegral value_d;

- declare a static debug level for all class instantiations:

      static Integral::DEBUG debug_level_d;

required public methods:

- static methods:

      static const String& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      static boolean setDebug(Integral::DEBUG level);

      boolean debug(const unichar* msg) const;

- destructor/constructor(s):

      ~MScalar()

      MScalar()

      MScalar(const MScalar& arg);

- assign methods:

      boolean assign(const MScalar& arg);

- operator= methods:

      we need to have the overloaded operator '=' defined in the derived classes instead of the base template class. this is required since c++ predefines the operator '=' for any class by default and this hides any other definition of this operator in the base class.

- i/o methods:

      long sofSize() const;

      boolean read(Sof& sof, long tag, const String& name = CLASS_NAME);

      boolean write(Sof& sof, long tag, const String& name = CLASS_NAME) const;

      boolean readData(Sof& sof, const String& pname = DEF_PARAM,long size = SofParser::FULL_OBJECT, boolean param_a = true, boolean nested_a = false);

      boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

- equality methods:

      boolean eq(const MScalar& compare_scalar) const;

- memory management methods:

      the new and delete methods are omitted because they are defined in the classes that instantiate this template

- clear method:

      boolean clear(Integral::CMODE = Integral::DEF_CMODE);

class-specific public methods:

- constructor method:

      this method is useful to have for the diagnose method.

- assign methods:

      MScalar(TIntegral arg));

      template<class TAIntegral>
      boolean assign(TAIntegral arg);

      boolean assign(const String& arg);

- get methods:

      boolean get(String& arg) const;

- memory size methods:

      long memSize() const;

- method present value:

      define functions which are used to wrap member functions that have different
      implementations for different data types, and return the correct value by
      using template specialization.

      TIntegral presentValue(double arg) const;

      TIntegral presentValue(complexdouble arg) const;

- method almostEqual

      boolean almostEqual(TIntegral arg) const;

      boolean almostEqual(TIntegral arg, double percent, double bound = Integral::DEF_BOUND) const;

- operator methods:

      operator TIntegral() const;

- arithmetic operator overload methods:

      TIntegral operator+(TIntegral arg) const;

      TIntegral operator-(TIntegral arg) const;

      TIntegral operator*(TIntegral arg) const;

      TIntegral operator/(TIntegral arg) const;

      TIntegral operator%(TIntegral arg) const;

- operator overload methods:

      TIntegral operator++();

      TIntegral operator--();

      TIntegral operator++(int);

      TIntegral operator--(int);

      MScalar& operator+=(TIntegral arg);

      MScalar& operator-=(TIntegral arg);

      MScalar& operator*=(TIntegral arg);

      MScalar& operator/=(TIntegral arg);

      MScalar& operator%=(TIntegral arg);

      boolean operator == (TIntegral arg) const;

      boolean operator != (TIntegral arg) const;

      boolean operator < (TIntegral arg) const;

      boolean operator <= (TIntegral arg) const;

      boolean operator > (TIntegral arg) const;

      boolean operator >= (TIntegral arg) const;

- equality and comparison methods:

      boolean eq(TIntegral arg) const;

      boolean eq(TIntegral arg1, TIntegral arg2) const;

      boolean ne(TIntegral arg) const;

      boolean lt(TIntegral arg) const;

      boolean le(TIntegral arg) const;

      boolean gt(TIntegral arg) const;

      boolean ge(TIntegral arg) const;

- bitwise methods:

      TIntegral band(TIntegral arg);

      TIntegral band(TIntegral arg1, TIntegral arg2);

      TIntegral bor(TIntegral arg);

      TIntegral bor(TIntegral arg1, TIntegral arg2);

      TIntegral bxor(TIntegral arg);

      TIntegral bxor(TIntegral arg1, TIntegral arg2);

      TIntegral brs(TIntegral incr);

      TIntegral brs(TIntegral arg, TIntegral incr);

      TIntegral bls(TIntegral incr);

      TIntegral bls(TIntegral arg, TIntegral incr);

      TIntegral bcmpl();

      TIntegral bcmpl(TIntegral arg);

- arithmetic methods:

      TIntegral add(TIntegral arg2);

      TIntegral add(TIntegral arg1, TIntegral arg2);

      TIntegral sub(TIntegral arg2);

      TIntegral sub(TIntegral arg1, TIntegral arg2);

      TIntegral mult(TIntegral arg2);

      TIntegral mult(TIntegral arg1, TIntegral arg2);

      TIntegral div(TIntegral arg2);

      TIntegral div(TIntegral arg1, TIntegral arg2);

      TIntegral mod(TIntegral arg2);

      TIntegral mod(TIntegral arg1, TIntegral arg2);

- other mathematical methods (listed alphabetically):

      TIntegral abs();

      TIntegral abs(TIntegral arg);

      TIntegral acos();

      TIntegral acos(TIntegral arg);

      TIntegral acosh();

      TIntegral acosh(TIntegral arg);

      TIntegral asin();

      TIntegral asin(TIntegral arg);

      TIntegral asinh();

      TIntegral asinh(TIntegral arg);

      TIntegral atan();

      TIntegral atan(TIntegral arg);

      TIntegral atanh();

      TIntegral atanh(TIntegral arg);

      TIntegral ceil();

      TIntegral ceil(TIntegral arg);

      TIntegral centerClip(TIntegral min, TIntegral max);

      TIntegral centerClip(TIntegral min, TIntegral max, TIntegral val);

      TIntegral cos();

      TIntegral cos(TIntegral arg);

      TIntegral cosh();

      TIntegral cosh(TIntegral arg);

      TIntegral exp();

      TIntegral exp(TIntegral arg);

      TIntegral exp2();

      TIntegral exp2(TIntegral arg);

      TIntegral exp10();

      TIntegral exp10(TIntegral arg);

      TIntegral factorial();

      TIntegral factorial(TIntegral arg);

      TIntegral floor();

      TIntegral floor(TIntegral arg);

      TIntegral fraction();

      TIntegral fraction(TIntegral arg);

      TIntegral grand(TIntegral mean, TIntegral stddev, Random& generator = Random::GLOBAL_GAUSSIAN);

      ulong hash(ulong hsize);

      TIntegral inverse();

      TIntegral inverse(TIntegral arg);

      TIntegral limit(TIntegral min, TIntegral max);

      TIntegral limit(TIntegral min, TIntegral max, TIntegral val);

      TIntegral limitMag(TIntegral thresh, TIntegral output);

      TIntegral limitMag(TIntegral thresh, TIntegral output, TIntegral val);

      TIntegral log();

      TIntegral log(TIntegral arg);

      TIntegral log2();

      TIntegral log2(TIntegral arg);

      TIntegral log10();

      TIntegral log10(TIntegral arg);

      TIntegral log1p();

      TIntegral log1p(TIntegral arg);

      TIntegral max(TIntegral arg);

      TIntegral max(TIntegral arg_1, TIntegral arg_2);

      TIntegral min(TIntegral arg);

      TIntegral min(TIntegral arg_1, TIntegral arg_2);

      TIntegral neg();

      TIntegral neg(TIntegral arg);

      TIntegral pow(TIntegral exponent);

      TIntegral pow(TIntegral arg, TIntegral exponent);

      TIntegral rand(Random& generator = Random::GLOBAL_UNIFORM);

      TIntegral rand(TIntegral min, TIntegral max, Random& generator = Random::GLOBAL_UNIFORM);

      TIntegral rceil();

      TIntegral rceil(TIntegral arg);

      TIntegral rfloor();

      TIntegral rfloor(TIntegral arg);

      TIntegral round();

      TIntegral round(TIntegral arg);

      TIntegral sign();

      TIntegral sign(TIntegral arg);

      TIntegral sin();

      TIntegral sin(TIntegral arg);

      TIntegral sinh();

      TIntegral sinh(TIntegral arg);

      TIntegral sqrt();

      TIntegral sqrt(TIntegral arg);

      TIntegral square();

      TIntegral square(TIntegral arg);

      TIntegral tan();

      TIntegral tan(TIntegral arg);

      TIntegral tanh();

      TIntegral tanh(TIntegral arg);

private methods:

- friend functions:

      friend class MScalarMethods;

- diagnose methods:

      static boolean diagnose0(Integral::DEBUG debug_level);

      static boolean diagnose1(Integral::DEBUG debug_level);

      static boolean diagnose2(Integral::DEBUG debug_level);

examples:

- This example shows how to do some basic mathematical and logical operations:

      MScalar<long, int32> val0;
      MScalar<long, int32> val1;
      MScalar<long, int32> val2;
      MScalar<double, float64> val3;
      MScalar<double, float64> val4;

      long data = 16;

      val0.assign((long)8);
      val0 += 2;
      if(!val0.eq(10)) {
          Error::handle(val0.name(), L"operator+=", Error::TEST,
                               __FILE__, __LINE__);
      }

      val4.assign((double)0.15);

      val3.log2(val4);
      val3*= val4;

      val0.round(val3);

      val1.assign(val0);
      val1.bor(data);

notes:

- The various types with bit-length specifications, e.g., float64, are defined in IntegralTypes.h. These are wrappers to encapsulate system- or language-specific data types and provide a consistent interface to data types throughout the IFCs. They are not intended to be used by system users.
- Many template specialization methods are used, such as the neg() for MScalar<ushort> and bitwise methods for MScalar<float>.
- The use of templates requires special documentation techniques. For example, in the required public methods section, above, if you click on the link to investigate the diagnose method,

      static boolean diagnose(Integral::DEBUG debug_level);

  you will be taken to a section showing the actual implementation of the diagnose method:

      template<class TIntegral, class TSize>
      boolean MScalarMethods::diagnose(Integral::DEBUG level_a) {
           // . . . code removed
           //
      }

  Notice that the header linked to does not match the header shown in the link. The match for the link actually is an statement occurring in MScalar.h, which looks like this:

      static boolean diagnose(Integral::DEBUG debug_level) {
           return MScalarMethods::diagnose<TIntegral, TSize>(debug_level);
      }

  The code in the header file merely sets up the template specialization and calls the template's diagnose class. Rather than pointing to this more or less meaningless code, we have chosen to link to the code which actually implements the call to diagnose, so the user is able to see the details of the implementation, rather than just the intermediate, though matching, code.
- While friend functions are generally discouraged in the ISIP environment, they are used in the MScalar class to circumvent the template delayed compilation problem.
- The setDebug method for this class is static because the debug_level is shared across all objects of this class type.
- Explicit template instantiations were replaced by a facility that generates the code for each data type, and compiles it. This is done using the make facility and some preprocessor macros. Code that previously looked like this:

      // define all pre-provided template instances
      //
      template boolean
      MScalarMethods::diagnose
      (Integral::DEBUG level);

      template boolean
      MScalarMethods::diagnose
      (Integral::DEBUG level);

      template boolean
      MScalarMethods::diagnose
      (Integral::DEBUG level);

      ...

  is replaced by this:

      MScalarMethods::diagnose<ISIP_TEMPLATE_TARGET>
      (Integral::DEBUG level);

  ISIP_TEMPLATE_TARGET is replaced by the preprocessor using a value defined in the make file. Generally speaking, the implementation is fairly straightforward and clean. However, a little more work was necessary to handle type-specific methods.