package nxm.sys.libm;

import nxm.sys.inc.Constants;
/**
    Defines interface for arithmetic operators.

    This class allows a subclass to be fully usable by the NeXtMidas primitives
    <code>CALC</code> and <code>FCALC</code>.
    primitives. <br>
    <br>
    See the NeXtMidas help/explain file for the <code>GENERATE OPER</code>
    primitive for details on how to automatically generating an operator
    subclass.<br>
    <br>

    <a id="iomodes"><b>I/O Modes:</b></a>
       The following table summarizes the available I/O modes for use:
       <table style="margin-left:auto;margin-right:auto;" border="1">
         <caption style="visibility:hidden">""</caption>
         <tr>
           <td style="text-align:center"><b>Mode</b></td>
           <td style="text-align:left"><b>Description</b></td>
         </tr>
         <tr>
           <td style="text-align:center">{@link #S}</td>
           <td style="text-align:left">Single scalar operand.</td>
         </tr>
         <tr>
           <td style="text-align:center">{@link #C}</td>
           <td style="text-align:left">Single complex operand.</td>
         </tr>
         <tr>
           <td style="text-align:center">{@link #V}</td>
           <td style="text-align:left">Single vector operand.</td>
         </tr>
          <tr>
           <td style="text-align:center">{@link #G}</td>
           <td style="text-align:left">Single complex-conjugate operand.</td>
         </tr>

       </table>
    <br>

    @author Jeff Schoen
*/
public class Operator extends Object implements Constants {

  /* data input/output modes S-scalar, C-complex, G-complexConjugate, V-vector(XYZ) */
  /** data mode S: scalar                             */ public static final int S    =    0x1;
  /** data mode C: complex                            */ public static final int C    =    0x2;
  /** data mode V: vector                             */ public static final int V    =    0x3;
  /** data mode G: complexConjugate                   */ public static final int G    =    0xA;
  /** data mode SS: scalar-scalar                     */ public static final int SS   =   0x11;
  /** data mode CS: complex-scalar                    */ public static final int CS   =   0x12;
  /** data mode SC: scalar-complex                    */ public static final int SC   =   0x21;
  /** data mode CC: complex-complex                   */ public static final int CC   =   0x22;
  /** data mode CG: complex-complexConjugate          */ public static final int CG   =   0xA2;
  /** data mode VS: vector-scalar                     */ public static final int VS   =   0x13;
  /** data mode VV: vector-vector                     */ public static final int VV   =   0x33;
  /** data mode SSS: scalar-scalar-scalar             */ public static final int SSS  =  0x111;
  /** data mode CSC: complex-scalar-complex           */ public static final int CSC  =  0x212;
  /** data mode SCC: scalar-complex-complex           */ public static final int SCC  =  0x221;
  /** data mode CCC: complex-complex-complex          */ public static final int CCC  =  0x222;
  /** data mode GCC: complexConjugate-complex-complex */ public static final int GCC  =  0xA22;
  /** data mode CGC: complex-complexConjugate-complex */ public static final int CGC  =  0x2A2;
  /** data mode VSV: vector-scalar-vector             */ public static final int VSV  =  0x313;
  /** data mode VVV: vector-vector-vector             */ public static final int VVV  =  0x333;
  /** data mode CCS: complex-complex-scalar           */ public static final int CCS  =  0x122;
  /** data mode VVS: vector-vector-scalar             */ public static final int VVS  =  0x133;
  /** data mode SSC: scalar-scalar-complex            */ public static final int SSC  =  0x211;
  /** data mode CSS: complex-scalar-scalar            */ public static final int CSS  =  0x112;
  /** data mode SSSS: scalar-scalar-scalar-scalar     */ public static final int SSSS = 0x1111;
  /** data mode SSSV: scalar-scalar-scalar-vector     */ public static final int SSSV = 0x3111;
  /** data mode VSSS: vector-scalar-scalar-scalar     */ public static final int VSSS = 0x1113;

  /** CNJA modifier mode */ public static final int CNJA=0x8;
  /** CNJB modifier mode */ public static final int CNJB=0x80;
  /** CNJC modifier mode */ public static final int CNJC=0x800;
  /** SNGA modifier mode */ public static final int SNGA=0x4;
  /** SNGB modifier mode */ public static final int SNGB=0x40;
  /** SNGC modifier mode */ public static final int SNGC=0x400;

  /** Return value indicating that a given function is not supported.
      @see #process(double[][],int,int)
      @see #process(double[][],int,int,double)
      @see #process(float[][],int,int)
      @see #process(float[][],int,int,double)
      @see #process(int[][],int,int)
      @see #process(int[][],int,int,double)
      @see #validate(char,int,int)
   */
  public static final int NOSUPPORT=-1;

  /** Any processing flags to use. */
  protected int flags;

  /** The scale factor to apply. */
  protected double scale;

  /** Creates a new instance. <br>
      This is the same as using <code>Operator(0, 1.0)</code>.
      @see #Operator(int,double)
   */
  public Operator() {
    this (0,1.0);
  }

  /** Creates a new instance. <br>
      This is the same as using <code>Operator(flags, 1.0)</code>.
      @param flags Any processing flags to use.
      @see #Operator(int,double)
   */
  public Operator(int flags) {
    this (flags,1.0);
  }

  /** Creates a new instance. <br>
      This is the same as using <code>Operator(0, scale)</code>.
      @param scale The scale factor to use.
      @see #Operator(int,double)
   */
  public Operator(double scale) {
    this (0,scale);
  }

  /** Creates a new instance.
      @param flags Any processing flags to use.
      @param scale The scale factor to use.
   */
  public Operator(int flags, double scale) {
    setFlags (flags);
    setScale (scale);
  }

  /** Apply this operator to <code>double</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The number of elements to operate on.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(double[][],int,int,double)
   */
  public int process (double[][] v, int n, int mode) {
    return NOSUPPORT;
  }

  /** Apply this operator to <code>double</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The return value to return if the computation completes.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @param scale The scale factor to apply.
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(double[][],int,int)
   */
  public int process (double[][] v, int n, int mode, double scale) {
    return NOSUPPORT;
  }

  /** Apply this operator to <code>float</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The return value to return if the computation completes.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(float[][],int,int,double)
   */
  public int process (float[][] v, int n, int mode) {
    return NOSUPPORT;
  }

  /** Apply this operator to <code>float</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The return value to return if the computation completes.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @param scale The scale factor to apply.
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(float[][],int,int)
   */
  public int process (float[][] v, int n, int mode, double scale) {
    return NOSUPPORT;
  }

  /** Apply this operator to <code>int</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The return value to return if the computation completes.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(int[][],int,int,double)
   */
  public int process (int[][] v, int n, int mode) {
    return NOSUPPORT;
  }

  /** Apply this operator to <code>int</code> arrays.
      @param v     The arrays to apply the operator to.
      @param n     The return value to return if the computation completes.
      @param mode  The input/output mode (see <a href="#iomodes">I/O Modes</a>).
      @param scale The scale factor to apply.
      @return The value of <code>n</code> if this method is supported or
              {@link #NOSUPPORT} if the operation is not supported.
      @see #process(int[][],int,int)
   */
  public int process (int[][] v, int n, int mode, double scale) {
    return NOSUPPORT;
  }

  /** Get the number of inputs for the operator.
      @return The number of inputs for the operator
              or <code>-1</code> if the number of inputs is undefined.
   */
  public int getInputs() {
    return -1;
  }

  /** Get the number of outputs for the operator.
      @return The number of outputs for the operator
              or <code>-1</code> if the number of inputs is undefined.
   */
  public int getOutputs() {
    return -1;
  }

  /** Sets the processing flags to use.
      @param value Any processing flags to use.
   */
  public void setFlags (int value) {
    flags=value;
  }

  /** Sets the scale factor to use.
      @param value The scale factor to use.
   */
  public void setScale (double value) {
    scale=value;
  }

  /** Check to see if a particular configuration is supported.
      @param type  The type to use. <i>This is usually ignored.</i>
      @param n     The number of elements to operate on.
      @param mode  The input/output mode to use (see <a href="#iomodes">I/O Modes</a>).
      @return The value of <code>n</code> if the configuration is supported or
              {@link #NOSUPPORT} if the operation is not supported.
   */
  public int validate(char type, int n, int mode) {
    return NOSUPPORT;
  }
}
