package nxm.sys.libm;

import nxm.sys.inc.DataTypes;
import nxm.sys.lib.Convert;
import nxm.sys.lib.Native;
import nxm.sys.lib.Shell;

/**
  Class to handle Fast Db calculations for real-time plotters
  This uses native routines where possible.

  @author Jeff Schoen
*/
public class Dbf extends Operator {

  /** default constructor */
  public Dbf () {}

  public int validate (char type, int n, int mode) {
    switch (mode) {
      case SS: break;
      default: n=NOSUPPORT;
    } return n;
  }

  public int getInputs() { return 1; }
  public int getOutputs() { return 1; }

  public final int process (float[][] v, int n, int mode) {
    if (v[0]!=v[1]) System.arraycopy (v[0],0, v[1],0, n);
    if (Native.useMath) Native.dbf(v[1],n,flags);
    else work(v[1],n,flags);
    return n;
  }

  public final int process (double[][] v, int n, int mode) {
    if (v[0]!=v[1]) System.arraycopy (v[0],0, v[1],0, n);
    work(v[1],n,flags);
    return n;
  }

  public final int process (int[][] v, int n, int mode) {
    if (v[0]!=v[1]) System.arraycopy (v[0],0, v[1],0, n);
    work(v[1],n,flags);
    return n;
  }

  /** Wrapper for computing dB log output on a buffer array
      @param buf   source array (can be of type double[], float[], or byte[])
      @param size  array size
      @param flags unused
   */
  public static void process (Object buf, int size, int flags) {
    if (buf instanceof double[]) work((double[])buf,size,flags);
    else if (Native.useMath) Native.dbf(buf,size,flags);
    else if (buf instanceof float[]) work((float[])buf,size,flags);
    else if (buf instanceof byte[]) work((byte[])buf,size,flags);
  }

  /** Computes dB log output on a buffer array of doubles
      @param buf   source array (type double[])
      @param size  array size
      @param flags unused
   */
  public static void work (double[] buf, int size, int flags) {
    double scale = (3.0/128);
    short iwork, offset=16384-128;
    for (int i=0; i<size; i++) {
      iwork = (short)(Float.floatToIntBits((float)buf[i])>>16);
      buf[i] = scale*(double)(iwork-offset);
    }
  }

  /** Computes dB log output on a buffer array of floats
      @param buf   source array (type float[])
      @param size  array size
      @param flags unused
   */
  public static void work (float[] buf, int size, int flags) {
    float scale=(float)(3.0/128);
    short iwork, offset=16384-128;
    for (int i=0; i<size; i++) {
      iwork = (short)(Float.floatToIntBits(buf[i])>>16);
      buf[i] = scale*(float)(iwork-offset);
    }
  }

  /** Computes dB log output on a buffer array of ints
      @param buf   source array (type int[])
      @param size  array size
      @param flags unused
   */
  public static void work (int[] buf, int size, int flags) {
    float scale=(float)(3.0/128);
    short iwork, offset=16384-128;
    for (int i=0; i<size; i++) {
      iwork = (short)(Float.floatToIntBits((float)buf[i])>>16);
      buf[i] = (int)(scale*(float)(iwork-offset));
    }
  }

  /**
   * Compute dB Log output using fast exponent overlay method.
   * Since NeXtMidas 2.7.0, this method mirrors Native.c's dbf() implementation.
   * @param buf input/output buffer (byte[] of float array) to work on
   * @param size size of buffer
   * @param flags not used here
   */
  public static void work (byte[] buf, int size, int flags) {
    final int SOFF = (Shell.rep == DataTypes.IEEE)? 0 : 1;
    float scale  = (float)(3.0/128);
    short offset = 16384-128;
    float fwork;
    for (int i=0,j=SOFF; i<size; i++,j+=2) {
      fwork = scale*(float)(Convert.unpackI(buf,j*2)-offset);
      Convert.packF(buf,i*4,fwork);
    }
  }
}
