name: MComplexScalar : public MScalar<SysComplex<TIntegral>, TSize>
synopsis:

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

>     #include <MComplexScalar.h>

>     MComplexScalar(const MComplexScalar& arg);
>     TIntegral rand(Random& generator = Random::GLOBAL_UNIFORM);
>     TSize read() const;
>     TSize imag() const;
>     double mag() const;
>     double angle() const;
>     TIntegral conjugate() const;

quick start:

>     MComplexScalar<complexdouble, float64> val0;
>     MComplexScalar<complexdouble, float64> val1;
>     MComplexScalar<complexdouble, float64> min_val;

>     val0.assign(complexdouble(10,2));
>     val0.exp2();
>     val1.exp10(2);

>     min_val.min(val0, val1);

description:
The MComplexScalar class is the base class for all complex scalar classes. It includes commonly used mathematical, logical, DSP, i/o and operator overload methods. MComplexScalar methods should not be used by users directly. They are intended to be used by other scalar, vector, and matrix complex classes.
dependencies:

- MScalar
- SofParser
- String
- MemoryManager
- MComplexScalarMethods.h

public constants:

- define the class name:

      static const String CLASS_NAME = L"MComplexScalar";

- i/o related constants:

      static const String DEF_PARAM = L"value";

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

      static const MComplexScalar DEF_VALUE;

error codes:

- error code indicating MComplexScalar class general error:

      static const long ERR = 21600;

protected data:

- 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):

      ~MComplexScalar()

      MComplexScalar()

      MComplexScalar(const MComplexScalar& arg);

- assign methods:

      assign methods are inherited from the MScalar class

- 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:

      equality methods are inherited from the MScalar class

- clear methods:

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

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

class-specific public methods:

- constructors:

      MComplexScalar(SysComplex arg);

      MComplexScalar(TIntegral arg);

- assign methods:

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

      template<class TAIntegral>
      boolean assign(TAIntegral real, TAIntegral imag);

      boolean assign(const String& arg);

- methods to provide alternate implementations (listed alphabetically):

      double angle() const;

      TCScalar conjugate() const;

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

      ulong hash(ulong hsize) const;

      TIntegral imag() const;

      double mag() const;

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

      SysComplex rand(TCScalar min, TCScalar max, Random& generator = Random::GLOBAL_UNIFORM;

      TIntegral real() const;

      TCScalar sign(TCScalar arg>);

private methods:

- friend functions:

      friend class MComplexScalarMethods;

      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:

      MComplexScalar<long, int32> val0;
      MComplexScalar<long, int32> val1;
      MComplexScalar<long, int32> val2;
      MComplexScalar<double, float64> val3;
      MComplexScalar<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 forbidden, such as the neg() for MComplexScalar<ushort> and the bitwise methods for MComplexScalar<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 is actually a statement occurring in MComplexScalar.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 the intermediate code, we link to the code which actually implements the call to diagnose so the user is able to see the actual details of the implementation.
- Generally, friend functions are discouraged but are used in the MComplexScalar 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 and compiles the code for each data type. 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
      MComplexScalarMethods::diagnose
      (Integral::DEBUG level);

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

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

      ...

  is replaced by this:

      MComplexScalarMethods::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 should be fairly straightforward and clean.