#ifdef HAS_PGPLOT
#include "cpgplot.h"
#endif /* HAS_PGPLOT */

#include <time.h>
#include <iostream>
#include <limits>
#include <cmath>
#include <memory>

#include "dpuser.h"
#include "functions.h"
#include "../libfits/dpComplex.h"
#include "procedures.h"
#include "dpuser_utils.h"
#include "dpuser.yacchelper.h"
#include "astrolib.h"
#include "fitting.h"
#include "JulianDay.h"
#include "platform.h"
#include "cube.h"
#include "dpuser_utils.h"
#include "gsl/gsl_sf_erf.h"
#include "gsl/gsl_sf_gamma.h"
#include "gsl/gsl_sf_bessel.h"
#include "gsl/gsl_rng.h"
#include "gsl/gsl_randist.h"
#include "kabsch/kabsch2d.h"

extern gsl_rng *gsl_rng_r;  /* global generator */

#ifdef DPQT
#include <QImage>
#include <QMutex>
#include "QFitsGlobal.h"
#include <QMessageBox>
extern QMutex *dpusermutex;

Fits *markposBuffer;
int DPQuestion;
#endif

#ifdef HAS_PYTHON
dpuserType getPythonVariable(const char *varname);
#endif

/*
 * available functions
 */
#define NUMBER typeCon|typeDbl|typeCom
#define REALNUM typeCon|typeDbl
#define ANYTHING REALNUM|typeStr|typeCom|typeFits|typeFitsFile|typeStrarr|typeDpArr

#ifdef _WINDOWS
#include <float.h>
/*returns 1 if x is positive infinity, and -1 if x is negative infinity.*/
int my_finite(double x)
{
    if (_fpclass(x) == _FPCLASS_PINF) {
        return 1;
    } else if (_fpclass(x) == _FPCLASS_NINF) {
        return -1;
    }

    return 0;
}

#define _ISINF my_finite
#else
#define _ISINF std::isinf
#endif

FunctionDeclaration::FunctionDeclaration(const char *n, int mi, int ma, long a[20], int no, const char *o[]) {
    int i, opt = 1;
    name = n;
    minargs = mi;
    maxargs = ma;
    for (i = 0; i < 20; i++) args[i] = a[i];
    noptions = no;
    for (i = 0; i < noptions; i++) {
        options[o[i]] = opt;
        opt *= 2;
    }
}

function_declarations funcss[] = {
    { "sin", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "cos", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "tan", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "sinh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "cosh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "tanh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "asin", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "acos", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "atan", 1, 2, { NUMBER|typeFits, NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "asinh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "acosh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "atanh", 1, 1, { NUMBER|typeFits }, 2, { "rad", "deg" } },
    { "exp", 1, 1, { NUMBER|typeFits }, 0 },
    { "log", 1, 2, { NUMBER|typeFits, NUMBER }, 0 },
    { "ln", 1, 1, { NUMBER|typeFits }, 0 },
    { "sqrt", 1, 1, { NUMBER|typeFits }, 0 },
    { "erf", 1, 1, { REALNUM }, 0 },
    { "bessel", 3, 3, { REALNUM, typeCon, typeCon }, 0 },
    { "int", 1, 1, { REALNUM|typeStr }, 0 },
    { "round", 1, 1, { REALNUM }, 0 },
    { "frac", 1, 1, { REALNUM }, 0 },
    { "abs", 1, 1, { NUMBER|typeFits }, 0 },
    { "sign", 1, 1, { REALNUM }, 0 },
    { "rad2deg", 1, 1, { NUMBER|typeFits }, 0 },
    { "deg2rad", 1, 1, { NUMBER|typeFits }, 0 },
    { "float", 1, 1, { typeStr|NUMBER|typeFits }, 0 },
    { "strlen", 1, 1, { typeStr }, 0 },
    { "min", 1, 2, { REALNUM|typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "max", 1, 2, { REALNUM|typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "avg", 1, 2, { typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "total", 1, 2, { REALNUM|typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "median", 1, 2, { typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "naxis", 1, 2, { typeFits|typeFitsFile|NUMBER, typeCon }, 0 },
    { "naxis1", 1, 2, { typeFits|typeFitsFile|NUMBER, typeCon }, 0 },
    { "naxis2", 1, 2, { typeFits|typeFitsFile|NUMBER, typeCon }, 0 },
    { "naxis3", 1, 2, { typeFits|typeFitsFile|NUMBER, typeCon }, 0 },
    { "xmax", 1, 1, { typeFits }, 0 },
    { "ymax", 1, 1, { typeFits }, 0 },
    { "xcen", 1, 1, { typeFits }, 0 },
    { "ycen", 1, 1, { typeFits }, 0 },
    { "real", 1, 1, { NUMBER|typeFits }, 0 },
    { "imag", 1, 1, { NUMBER|typeFits }, 0 },
    { "arg", 1, 1, { NUMBER|typeFits }, 0 },
    { "jd", 3, 6, { typeCon, typeCon, typeCon, typeCon, typeCon, REALNUM }, 0 },
    { "jdnumber", 3, 6, { typeCon, typeCon, typeCon, typeCon, typeCon, REALNUM }, 0 },
    { "jdfraction", 3, 6, { typeCon, typeCon, typeCon, typeCon, typeCon, REALNUM }, 0 },
    { "upper", 1, 1, { typeStr }, 0 },
    { "lower", 1, 1, { typeStr }, 0 },
    { "string", 1, 1, { NUMBER|typeStr }, 3, { "time", "deg", "rad" } },
    { "calday", 1, 2, { REALNUM, REALNUM }, 1, { "mjd" } },
    { "header", 1, 2, { typeFits|typeFitsFile, typeCon }, 0 },
    { "dayofweek", 1, 3, { REALNUM, REALNUM, typeCon }, 0 },
    { "fits", 1, 3, { typeCon|typeStr, typeCon, typeCon }, 0 },
    { "gauss", 1, 7, { REALNUM|typeFits, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "circle", 3, 5, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "ellipse", 3, 7, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "rect", 4, 6, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "delta", 2, 5, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "cosbell", 4, 6, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "chinhat", 3, 5, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "airy", 3, 5, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "cubemedian", 1, 3, { typeFits|typeFitsFile, REALNUM, typeCon }, 0 },
    { "cubeavg", 1, 3, { typeFits|typeFitsFile|typeStrarr, REALNUM, typeCon }, 0 },
    { "ssa", 7, 8, { typeFits|typeFitsFile|typeStrarr, NUMBER, NUMBER, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeCon }, 1, { "resize" } },
    { "mosaic", 1, 4, { typeStr|typeStrarr, typeFits, typeFits, typeFits }, 0 },
    { "shift", 3, 4, { typeFits, REALNUM, REALNUM, REALNUM }, 4, { "wrap", "linear", "fft", "poly3" } },
    { "rotate", 2, 4, { typeFits, REALNUM, REALNUM, REALNUM }, 0 },
    { "fft", 1, 1, { typeFits }, 0 },
    { "reass", 1, 1, { typeFits }, 0 },
    { "norm", 1, 1, { typeFits }, 3, { "unity", "total", "average" } },
    { "clip", 3, 4, { typeFits, REALNUM, REALNUM, REALNUM }, 0 },
    { "smooth", 2, 2, { typeFits, REALNUM }, 4, { "xy", "z", "x", "y" } },
    { "boxcar", 2, 2, { typeFits, typeCon }, 8, { "average", "minimum", "maximum", "median", "xy", "x", "y", "z" } },
    { "3dmerge", 2, 3, { typeFits, typeFits, typeCon }, 0 },
    { "3dmegacal", 3, 3, { typeFits, typeStr, typeStr }, 0 },
    { "3dcal", 2, 2, { typeFits, typeFits }, 0 },
    { "3dcubin", 4, 4, { typeFits, typeCon, typeStr, REALNUM }, 0 },
    { "3dexpand", 1, 1, { typeFits }, 0 },
    { "dpixcreate", 2, 4, { typeFits, REALNUM, typeCon, typeCon }, 0 },
    { "dpixapply", 2, 4, { typeFits, typeFits, typeCon, typeCon }, 2, { "spiffik", "bezier" } },
    { "flip", 2, 2, { typeFits, typeCon }, 0 },
    { "enlarge", 2, 3, { typeFits, typeCon, typeCon }, 0 },
    { "resize", 3, 4, { typeFits, typeCon, typeCon, typeCon }, 0 },
    { "wien", 2, 3, { typeFits, typeFits, NUMBER }, 1, { "old" } },
    { "lucy", 3, 4, { typeFits, typeFits, typeCon, REALNUM }, 1, { "old" } },
    { "center", 1, 1, { typeFits }, 0 },
    { "3dnorm", 2, 2, { typeFits, typeStr }, 0 },
    { "conj", 1, 1, { typeFits | typeCom }, 0 },
    { "correl", 2, 2, { typeFits, typeFits }, 1, { "real" } },
    { "readfits", 1, 7, { typeStr, typeCon, typeCon, typeCon, typeCon, typeCon, typeCon }, 0 },
    { "3dspec", 2, 5, { typeFits, typeFits|typeCon, typeCon, typeCon, typeCon }, 3, "sum", "average", "median" },
    { "stddev", 1, 2, { typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "variance", 1, 2, { typeFits, REALNUM }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "meddev", 1, 1, { typeFits }, 6, "x", "y", "z", "xy", "xz", "yz" },
    { "saomark", 0, 0, { typeCon }, 0 },
    { "random", 0, 1, { typeCon }, 0 },
    { "import", 1, 5, { typeStr, typeCon, typeStr, typeStr, typeCon }, 2, { "number", "text" } },
    { "rebin", 3, 4, { typeFits, typeCon, typeCon, typeCon }, 0 },
    { "stringarray", 1, 1, { typeCon|typeStr }, 0 },
    { "nelements", 1, 1, { ANYTHING }, 0 },
    { "ssastat", 7, 8, { typeFitsFile, NUMBER, NUMBER, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeCon }, 0 },
    { "sssa", 6, 7, { typeFitsFile, typeFits, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeFits|typeCon, typeCon }, 0 },
    { "ssaselect", 6, 6, { typeFits, REALNUM, REALNUM, REALNUM, REALNUM, REALNUM }, 0 },
    { "maxentropy", 3, 4, { typeFits, typeFits, typeCon, REALNUM }, 0 },
    { "cubeminimum", 1, 1, { typeFits }, 0 },
    { "cubemaximum", 1, 1, { typeFits }, 0 },
    { "fwhm", 3, 4, { typeFits, typeCon, typeCon, typeCon }, 0 },
    { "setbitpix", 2, 4, { typeFits, typeCon, REALNUM, REALNUM }, 0 },
    { "bytearray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "shortarray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "longarray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "floatarray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "doublearray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "complexarray", 1, 3, { typeCon, typeCon, typeCon }, 0 },
    { "shrink", 2, 3, { typeFits, typeCon, typeCon }, 0 },
    { "getfitskey", 2, 3, { typeFits|typeFitsFile, typeStr, typeCon }, 1, { "text" } },
    { "polyfit", 2, 3, { typeFits, typeCon, typeId|ANYTHING }, 0 },
    { "sprintf", 2, 2, { typeStr, REALNUM }, 0 },
    { "photometry", 5, 5, { typeFits, typeFits, typeFits, typeCon, typeCon }, 11, { "u", "b", "v", "r", "i", "j", "h", "k", "l", "m", "n" } },
    { "transcoords", 3, 5, { typeFits, typeFits, typeFits, typeId|ANYTHING, typeId|ANYTHING }, 4, { "linear", "cubic", "silent", "rotation" } },
    { "findfile", 1, 1, { typeStr }, 0 },
    { "markpos", 1, 2, { typeId|typeFits, typeCon }, 3, { "center", "centroid", "gauss" } },
    { "lmst", 1, 2, { REALNUM, REALNUM }, 0 },
    { "wsa", 10, 11, { typeFitsFile, typeCon, typeCon, REALNUM, typeCon, typeCon, typeFits, typeFits, typeFits, typeFits, typeFits }, 0 },
    { "swsa", 11, 12, { typeFitsFile, typeFits, typeCon, typeCon, REALNUM, typeCon, typeCon, typeFits, typeFits, typeFits, typeFits, typeFits }, 0 },
    { "centroids", 3, 3, { typeFits, typeFits, typeCon }, 0 },
    { "maxima", 3, 3, { typeFits, typeFits, typeCon }, 2, { "circle", "box" } },
    { "fileexists", 1, 1, { typeStr }, 0 },
    { "filesize", 1, 1, { typeStr }, 0 },
    { "dir", 0, 1, { typeStr }, 1, { "recursive" } },
    { "polyfitxy", 3, 4, { typeFits, typeFits, typeCon, typeId|ANYTHING }, 0 },
    { "sort", 1, 1, { typeFits|typeStr|typeStrarr }, 1, { "reverse" } },
    { "char", 1, 1, { typeCon }, 0, },
    { "complex", 2, 2, { REALNUM|typeFits, REALNUM|typeFits }, 0, },
    { "strpos", 2, 2, { typeStr|typeStrarr, typeStr }, 1, { "nocase" } },
    { "clean", 4, 5, { typeFits, typeFits, typeCon, REALNUM, typeId|ANYTHING }, 0 },
    { "collapse", 2, 2, { typeFits, typeCon }, 0 },
    { "magnify", 2, 3, { typeFits, typeCon, REALNUM }, 0, },
    { "wsastat", 10, 11, { typeFitsFile, typeCon, typeCon, REALNUM, typeCon, typeCon, typeFits, typeFits, typeFits, typeFits, typeFits }, 0 },
    { "gaussfit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "gauss2dfit", 3, 4, { typeFits, typeFits, typeFits, typeId|ANYTHING }, 0, },
    { "polyfitxyerr", 4, 5, { typeFits, typeFits, typeCon, REALNUM|typeFits, typeId|ANYTHING }, 0 },
    { "psf", 2, 2, { typeFits, typeFits }, 4, { "median", "average", "minimum", "maximum" } },
    { "pwd", 0, 0, { typeCon }, 0 },
    { "quickgauss", 4, 4, { NUMBER, NUMBER, NUMBER, typeCon }, 0 },
    { "getenv", 1, 1, { typeStr }, 0, },
    { "cblank", 1, 2, { typeFits, REALNUM }, 0 },
    { "now", 0, 1, { typeCon }, 0 },
    { "pgband", 7, 7, { typeCon, typeCon, REALNUM, REALNUM, typeId|REALNUM, typeId|REALNUM, typeId|ANYTHING }, 0 },
    { "pgbeg", 4, 4, { typeCon, typeStr, typeCon, typeCon }, 0 },
    { "pgbegin", 4, 4, { typeCon, typeStr, typeCon, typeCon }, 0 },
    { "pgcurs", 3, 3, { typeId|REALNUM, typeId|REALNUM, typeId|ANYTHING }, 0 },
    { "pgcurse", 3, 3, { typeId|REALNUM, typeId|REALNUM, typeId|ANYTHING }, 0 },
    { "pgopen", 1, 1, { typeStr }, 0 },
    { "pgrnd", 2, 2, { REALNUM, typeId|ANYTHING }, 0 },
    { "polar", 2, 2, { typeFits|REALNUM, typeFits|REALNUM }, 0 },
    { "transmatrix", 2, 4, { typeFits, typeFits, typeId|ANYTHING, typeId|ANYTHING }, 5, { "linear", "rotation", "cubic", "silent", "rigid"} },
    { "transform", 2, 2, { typeFits, typeFits }, 0, },
    { "invert", 1, 1, { typeFits }, 0, },
    { "transpose", 1, 1, { typeFits }, 0, },
    { "isvariable", 1, 1, { typeStr|typeId }, 0, },
    { "pi", 0, 0, { typeCon }, 0, },
    { "convolve", 2, 2, { typeFits, typeFits }, 0, },
    { "gammp", 2, 2, { REALNUM, REALNUM }, 0, },
    { "reform", 1, 4, { typeFits|NUMBER, typeCon, typeCon, typeCon }, 0, },
    { "find", 3, 5, { typeFits, REALNUM, REALNUM, typeFits, typeFits }, 1, { "silent" } },
    { "histogram", 1, 4, { typeFits, REALNUM, REALNUM, REALNUM }, 1, { "reverse" } },
    { "meandev", 1, 2, { typeFits, REALNUM }, 0, },
    { "version", 0, 0, { typeCon }, 0 },
    { "spifficube", 1, 1, { typeFits }, 2, { "K", "HK" } },
    { "spiffiuncube", 1, 1, { typeFits }, 2, { "K", "HK" } },
    { "spiffishift", 1, 1, { typeFits }, 2, { "K", "HK" } },
    { "bezier", 1, 2, { typeFits, typeCon }, 0, },
    { "bezier1d", 2, 2, { typeFits, typeFits }, 0, },
    { "moffat", 4, 8, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "readfitsextension", 2, 8, { typeStr, typeCon|typeStr, typeCon, typeCon, typeCon, typeCon, typeCon, typeCon }, 0 },
    { "multigauss2dfit", 3, 4, { typeFits, typeFits, typeFits, typeId|ANYTHING }, 0, },
    { "sincfit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "rebin1d", 4, 5, { typeFits, REALNUM, REALNUM, REALNUM, typeFits }, 0},
    { "velmap", 3, 4, { typeFits, REALNUM, REALNUM, REALNUM }, 2, { "gauss", "centroid"} },
    { "fxcor", 2, 2, { typeFits, typeFits }, 0 },
    { "correlmap", 2, 2, { typeFits, typeFits }, 0 },
    { "longslit", 5, 6, { typeFits, typeCon, typeCon, REALNUM, typeCon, REALNUM }, 0 },
    { "evalvelmap", 2, 2, { typeFits, typeFits }, 0 },
    { "sinfit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "indexbase", 0, 0, { typeCon }, 0 },
    { "voronoi", 4, 4, { typeFits, typeFits, typeFits, REALNUM }, 1, { "map" } },
    { "gauss2dsimplefit", 4, 5, { typeFits, REALNUM, REALNUM, REALNUM, typeId|ANYTHING }, 0 },
    { "transpoly", 3, 3, { typeFits, typeFits, typeFits }, 0 },
    { "strtrim", 1, 1, { NUMBER|typeStr|typeStrarr }, 0 },
    { "right", 2, 2, { typeStr, typeCon }, 0 },
    { "ten", 3, 3, {REALNUM, REALNUM, REALNUM }, 0 },
    { "primes", 1, 1, { typeCon }, 0 },
    { "twodcut", 5, 5, { typeFits, typeCon, typeCon, REALNUM, typeCon }, 0 },
    { "simplifywhitespace", 1, 1, { typeStr }, 0},
    { "strsplit", 1, 2, { typeStr, typeStr }, 0},
    { "interpol", 3, 3, { typeFits, typeFits, typeFits }, 0 },
    { "sersic2dfit", 3, 4, { typeFits, typeFits, typeFits, typeId|ANYTHING }, 0, },
    { "sersic2dsimplefit", 4, 6, { typeFits, REALNUM, REALNUM, REALNUM, typeId|ANYTHING, REALNUM }, 0 },
    { "sersicfit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "sersic2d", 6, 8, { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER }, 0 },
    { "randomg", 1, 2, { REALNUM, typeCon }, 0 },
    { "poly", 2, 3, { NUMBER|typeFits, typeFits, typeCon}, 0 },
    { "getbitpix", 1, 1, { typeFits }, 0 },
    { "isnan", 1, 1, { NUMBER }, 0 },
    { "isinf", 1, 1, { NUMBER }, 0 },
    { "polyfit2d", 2, 3, { typeFits, typeCon, typeId|ANYTHING }, 0},
    { "polyfit2derr", 3, 4, { typeFits, typeCon, REALNUM|typeFits, typeId|ANYTHING }, 0},
    { "interpolate", 3, 4, { typeFits, REALNUM, REALNUM , typeCon}, 0},
    { "radialprofile", 3, 3, { typeFits, typeCon, typeCon}, 0},
    { "ellipticalprofile", 6, 6, { typeFits, typeCon, typeCon, REALNUM, REALNUM, typeCon}, 0},
    { "multigaussfit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "evalgaussfit", 2, 2, { typeFits|REALNUM, typeFits }, 0 },
    { "polyroots", 1, 2, { typeFits, typeCon }, 0 },
    { "xmin", 1, 1, { typeFits }, 0 },
    { "ymin", 1, 1, { typeFits }, 0 },
    { "readfitsall", 1, 1, { typeStr }, 0 },
    { "cubequantile", 2, 2, { typeFits|typeFitsFile, REALNUM }, 0 },
    { "quantile", 2, 2, { typeFits, REALNUM }, 0 },
    { "straightlinefit", 4, 5, { typeFits, typeFits, typeFits, typeFits, typeId|ANYTHING }, 0 },
    { "sersic2dsmoothfit", 4, 5, { typeFits, typeFits, REALNUM, typeFits, typeId|ANYTHING }, 0, },
    { "sersic2dsmoothsimplefit", 6, 7, { typeFits, typeFits, typeCon, typeCon, typeCon, REALNUM, typeId|ANYTHING, REALNUM }, 0 },
    { "test2dfit", 3, 4, { typeFits, typeFits, typeFits, typeId|ANYTHING }, 0, },
    { "bintablecol", 2, 2, { typeFits, typeCon|typeStr }, 0 },
    { "readfitsbintable", 2, 3, { typeStr, typeCon|typeStr, typeCon|typeStr }, 0 },
    { "listfitsextensions", 1, 1, { typeStr }, 0 },
    { "listtablecolumns", 2, 2, { typeStr, typeStr }, 0 },
    { "list", 1, 10, { typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr, typeFits|typeStrarr }, 0 },
    { "where", 1, 2, { typeFits, typeId|ANYTHING }, 0 },
    { "mpfit", 5, 5, { typeFits, typeFits, typeFits, typeFits, typeStr }, 0 },
    { "evalmpfit", 3, 3, { typeFits, typeFits, typeStr }, 0 },
    { "mpfitvars", 1, 1, { typeStr }, 0 },
    { "gausspos", 3, 3, { typeFits, typeFits, typeCon }, 0 },
    { "question", 1, 1, { typeStr }, 0 },
    { "nparams", 0, 1, { typeCon }, 0 },
    { "double", 1, 1, { typeStr|NUMBER|typeFits }, 0 },
    { "pyvar", 1, 1, { typeStr }, 0 },
    { "mjd", 1, 6, { REALNUM, REALNUM, typeCon, typeCon, typeCon, REALNUM }, 0 },
    { "replace", 3, 3, { typeStr|typeStrarr, typeStr, typeStr }, 0, },
    { "subpixel", 3, 3, { typeFits, REALNUM, REALNUM }, 0 },
    { "distort", 3, 3, { typeFits, typeFits, typeFits }, 0 },
    { "worldpos", 2, 2, { typeFits, typeFits }, 0 },
    { "pixpos", 2, 2, { typeFits, typeFits }, 0 },
    { "exec", 1, 1, { typeStr }, 0 },
    { "", 0, 0, { typeCon }, 0 }
};

//typedef dpuserType (*MyDecl)(void);

void init_functions() {
    funcs.reserve(300);

    int i = 0;
    while (strcmp(funcss[i].name, "") != 0) {
        funcs.push_back(FunctionDeclaration(
        funcss[i].name,
        funcss[i].minargs,
        funcss[i].maxargs,
        funcss[i].args,
        funcss[i].noptions,
        funcss[i].options));
        i++;
    }
}

/* process a function */

dpuserType resolveFunction(int id, std::vector<ASTNode *>args, std::vector<std::string>options) {
    dpuserType funcargs[20];
    dpuserType arguments[20];
    dpuserType rv, er;
    int nargs = 0;
    int optArgI[20], success;
    long onaxis1, onaxis2, omethod;

    onaxis1 = dpuser_vars["naxis1"].lvalue;
    onaxis2 = dpuser_vars["naxis2"].lvalue;
    omethod = dpuser_vars["method"].lvalue;

    rv.lvalue = 0;
    rv.svalue = NULL;
    rv.cvalue = NULL;
    rv.fvalue = NULL;
    rv.ffvalue = NULL;
    rv.arrvalue = NULL;
    rv.dparrvalue = NULL;
    rv.type = typeCon;
    er.lvalue = 0;
    er.svalue = NULL;
    er.cvalue = NULL;
    er.fvalue = NULL;
    er.ffvalue = NULL;
    er.arrvalue = NULL;
    er.dparrvalue = NULL;
    er.type = typeUnknown;

    int function_options = 0;

    if (options.size() > 0) {
        if (funcs[id].noptions == 0) {
            dp_output("WARNING - Function %s does not support options [/%s].\n",
                  options[0].c_str());
        } else {
            for (int i = 0; i < options.size(); i++) {
                if (funcs[id].options.count(options[i])) {
                    function_options |= funcs[id].options[options[i]];
                } else {
                    dp_output("WARNING - Ignoring invalid option /%s for function %s.\n",
                               options[i].c_str(), funcs[id].name.c_str());
                }
            }
        }
    }
    success = 1;

    // resolve keywords
    for (int i = 0; i < args.size(); i++) {
        if (dynamic_cast<assignmentNode *>(args.at(i)) != NULL) {
            args.at(i)->evaluate();
        } else {
            variableNode *var = dynamic_cast<variableNode *>(args.at(i));
            if (!(funcs[id].args[i] & typeId)) {
                funcargs[nargs] = args.at(i)->evaluate();
            } else if (funcs[id].args[i] == typeId|ANYTHING) {
                if (var != NULL) {
                    funcargs[nargs].type = typeId;
                    funcargs[nargs].svalue = CreateString(var->id);
                } else {
                    funcargs[nargs] = args.at(i)->evaluate();
                }
            } else {
                funcargs[nargs].type = typeId;
                funcargs[nargs].svalue = CreateString(var->id);
            }
            if (funcargs[nargs].type == typeUnknown) {
                success = FALSE;
            }
            nargs++;
        }
    }
    if (!success) {
        return er;
    }

    // Check number of arguments
    if (nargs < funcs[id].minargs) {
        dp_output("%s: ", funcs[id].name.c_str());
        yyerror("Too few arguments for function\n");
        success = 0;
    } else if (nargs > funcs[id].maxargs) {
        dp_output("%s: ", funcs[id].name.c_str());
        yyerror("Too many arguments for function\n");
        success = 0;
    }

    // convert typeStr to typeFitsFile and vice versa, if appropriate
    for (int i = 0; i < nargs; i++) {
        if (funcargs[i].type == typeStr) {
            if (!(funcs[id].args[i] & typeStr)) {
                if (funcs[id].args[i] & typeFitsFile) {
                    funcargs[i].type = typeFitsFile;
                    funcargs[i].ffvalue = funcargs[i].svalue;
                }
                if (funcs[id].args[i] & typeFits) {
                    funcargs[i].type = typeFitsFile;
                    funcargs[i].ffvalue = funcargs[i].svalue;
                }
            }
        } else if (funcargs[i].type == typeFitsFile) {
            if (!(funcs[id].args[i] & typeFitsFile)) {
                if (!(funcs[id].args[i] & typeFits)) {
                    if (funcs[id].args[i] & typeStr) {
                        funcargs[i].type = typeStr;
                        funcargs[i].svalue = funcargs[i].ffvalue;
                    }
                }
            }
        }
    }

    // check for variables to be created
/*@
    for (int i = 0; i < nargs; i++) {
        if (funcs[id].args[i] == (typeId|ANYTHING)) {
            if (funcargs[i].type == typeFitsFile) {
                int index = createVariable((char *)funcargs[i].ffvalue->c_str());
                dpuser_vars[*funcargs[i].ffvalue].type = typeCon;
                funcargs[i].type = typeId;
                funcargs[i].lvalue = index;
                p->fnc.op[i]->id.i = index;
            }
            if ((p->fnc.op[i]->id.i >= 0) && (p->fnc.op[i]->id.i < nvariables)) {
                variables[p->opr.op[i]->id.i] = rv;
            }
        }
    }
*/
    // check argument types
    if (success) {
        for (int i = 0; i < nargs; i++) {
            if (!(funcargs[i].type & funcs[id].args[i])) {
                if ((funcs[id].args[i] & typeFits) && (funcargs[i].type == typeFitsFile)) {
                    funcargs[i].fvalue = CreateFits();
                    success = funcargs[i].fvalue->ReadFITS(funcargs[i].ffvalue->c_str());
                    funcargs[i].type = typeFits;
                } else {
                    yyerror("is of wrong type");
                    success = 0;
                }
            }
            if (success) if (funcargs[i].type == typeCon) {
                funcargs[i].dvalue = (double)funcargs[i].lvalue;
                if ((funcs[id].args[i] & typeDbl)) {
                    funcargs[i].type = typeDbl;
                }
            }
/*@
            if (success) if (funcargs[i].type == typeId) {
                if (!(variables[p->fnc.op[i]->id.i].type & funcs[id].args[i])) {
                    dp_output("%s: Argument %i", funcs[id].name.c_str(), i + 1);
                    yyerror(" is of wrong type");
                    success = 0;
                } else {
                    funcargs[i].lvalue = p->fnc.op[i]->id.i;
                }
            }
*/
        }
    }
    if (success) {
        rv.type = funcargs[0].type;
    }
        // now process function
        if (success)
            switch (id+1) {

/************************
 ***      sin         ***
 ************************/
        case 1:
//            rv = dpuserFunction_sin(arguments[0], options).toConValue();
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = sin(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = sin(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_sin(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_sin(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                rv.clone(funcargs[0]);
                if (success) {
                    rv.fvalue->Sin(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      cos         ***
 ************************/
        case 2:
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = cos(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = cos(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_cos(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_cos(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Cos(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      tan         ***
 ************************/
        case 3:
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = tan(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = tan(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_tan(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_tan(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Tan(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      sinh        ***
 ************************/
        case 4:
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = sinh(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = sinh(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_sinh(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_sinh(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Sinh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      cosh        ***
 ************************/
        case 5:
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = cosh(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = cosh(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_cosh(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_cosh(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Cosh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      tanh        ***
 ************************/
        case 6:
            if (rv.type == typeDbl) {
                if (function_options == 2) rv.dvalue = tanh(funcargs[0].dvalue * M_PI / 180.);
                else rv.dvalue = tanh(funcargs[0].dvalue);
            } else if (rv.type == typeCom) {
                if (function_options == 2) rv.cvalue = CreateComplex(complex_tanh(*funcargs[0].cvalue * M_PI / 180.));
                else rv.cvalue = CreateComplex(complex_tanh(*funcargs[0].cvalue));
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Tanh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      asin        ***
 ************************/
        case 7:
            if (rv.type == typeDbl) {
                if (fabs(funcargs[0].dvalue) <= 1.0) {
                    rv.dvalue = asin(funcargs[0].dvalue);
                    if (function_options == 2) rv.dvalue *= 180. / M_PI;
                } else {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_asin(dpComplex(funcargs[0].dvalue, 0.0)));
                    if (function_options == 2) *rv.cvalue *= 180. / M_PI;
                }
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_asin(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Asin(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      acos        ***
 ************************/
        case 8:
//            rv = dpuserFunction_acos(arguments[0], options).toConValue();
            if (rv.type == typeDbl) {
                if (fabs(funcargs[0].dvalue) <= 1.0) {
                    rv.dvalue = acos(funcargs[0].dvalue);
                    if (function_options == 2) rv.dvalue *= 180. / M_PI;
                } else {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_acos(dpComplex(funcargs[0].dvalue, 0.0)));
                    if (function_options == 2) *rv.cvalue *= 180. / M_PI;
                }
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_acos(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Acos(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      atan        ***
 ************************/
        case 9:
            if (rv.type == typeDbl) {
                if (nargs == 1)
                    rv.dvalue = atan(funcargs[0].dvalue);
                else
                    rv.dvalue = atan2(funcargs[0].dvalue, funcargs[1].dvalue);
                if (function_options == 2) rv.dvalue *= 180. / M_PI;
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_atan(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    if (funcargs[1].type == typeFits) {
                        rv.fvalue->Atan2(*funcargs[1].fvalue, function_options != 2);
                    } else {
                        rv.fvalue->Atan(function_options != 2);
                    }
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      asinh       ***
 ************************/
        case 10:
            if (rv.type == typeDbl) {
                rv.dvalue = asinh(funcargs[0].dvalue);
                if (function_options == 2) rv.dvalue *= 180. / M_PI;
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_asinh(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Asinh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      acosh       ***
 ************************/
        case 11:
            if (rv.type == typeDbl) {
                if (funcargs[0].dvalue >= 1.0) {
                    rv.dvalue = acosh(funcargs[0].dvalue);
                    if (function_options == 2) rv.dvalue *= 180. / M_PI;
                } else {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_acosh(dpComplex(funcargs[0].dvalue, 0.0)));
                    if (function_options == 2) *rv.cvalue *= 180. / M_PI;
                }
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_acosh(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Acosh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      atanh       ***
 ************************/
        case 12:
            if (rv.type == typeDbl) {
                if (fabs(funcargs[0].dvalue) < 1.0) {
                    rv.dvalue = atanh(funcargs[0].dvalue);
                    if (function_options == 2) rv.dvalue *= 180. / M_PI;
                } else {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_atanh(dpComplex(funcargs[0].dvalue, 0.0)));
                    if (function_options == 2) *rv.cvalue *= 180. / M_PI;
                }
            } else if (rv.type == typeCom) {
                rv.cvalue = CreateComplex(complex_atanh(*funcargs[0].cvalue));
                if (function_options == 2) *rv.cvalue *= 180. / M_PI;
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Atanh(function_options != 2);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      exp         ***
 ************************/
        case 13:
            if (rv.type == typeDbl) rv.dvalue = exp(funcargs[0].dvalue);
            else if (rv.type == typeCom) rv.cvalue = CreateComplex(complex_exp(*funcargs[0].cvalue));
            else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Exp();
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      log         ***
 ************************/
        case 14:
            if (rv.type == typeDbl) {
                if (nargs == 1) {
                    if (funcargs[0].dvalue < 0.0) {
                        rv.type = typeCom;
                        rv.cvalue = CreateComplex(complex_log(dpComplex(funcargs[0].dvalue, 0.0) / log(10.0)));
                    } else {
                        rv.dvalue = log(funcargs[0].dvalue) / log(10.0);
                    }
                } else {
                    if ((funcargs[0].dvalue < 0.0) || (funcargs[1].dvalue < 0.0)) {
                        rv.type = typeCom;
                        rv.cvalue = CreateComplex(complex_log(dpComplex(funcargs[0].dvalue, 0.0) / complex_log(dpComplex(funcargs[0].dvalue, 0.0))));
                    } else {
                        rv.dvalue = log(funcargs[0].dvalue) / log(funcargs[1].dvalue);
                    }
                }
            } else if (rv.type == typeCom) {
                if (nargs == 1)
                    rv.cvalue = CreateComplex(complex_log(*funcargs[0].cvalue) / complex_log(dpComplex(10.0)));
                else if (funcargs[1].type == typeDbl)
                    rv.cvalue = CreateComplex(complex_log(*funcargs[0].cvalue) / complex_log(dpComplex(funcargs[1].dvalue)));
                else
                    rv.cvalue = CreateComplex(complex_log(*funcargs[0].cvalue) / complex_log(*funcargs[1].cvalue));
            }
            else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    if (nargs == 1)
                        rv.fvalue->Log();
                    else
                        rv.fvalue->Log(funcargs[1].dvalue);
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***       ln         ***
 ************************/
        case 15:
            if (rv.type == typeDbl)
                if (funcargs[0].dvalue < 0.0) {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_log(dpComplex(funcargs[0].dvalue, 0.0)));
                } else
                    rv.dvalue = log(funcargs[0].dvalue);
            else if (rv.type == typeCom) rv.cvalue = CreateComplex(complex_log(*funcargs[0].cvalue));
            else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Ln();
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      sqrt        ***
 ************************/
        case 16:
            if (rv.type == typeDbl)
                if (funcargs[0].dvalue < 0.0) {
                    rv.type = typeCom;
                    rv.cvalue = CreateComplex(complex_sqrt(dpComplex(funcargs[0].dvalue, 0.0)));
                } else rv.dvalue = sqrt(funcargs[0].dvalue);
            else if (rv.type == typeCom) rv.cvalue = CreateComplex(complex_sqrt(*funcargs[0].cvalue));
            else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Sqrt();
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      erf         ***
 ************************/
        case 17: rv.dvalue = gsl_sf_erf(funcargs[0].dvalue);
            break;

/************************
 ***     bessel       ***
 ************************/
        case 18: {
            int order, kind;
            kind = funcargs[1].lvalue;
            order = funcargs[2].lvalue;
            if ((order < 0) || (kind < 1) || (kind > 2)) {
                yyerror("Bessel: illegal argument\n");
                success = 0;
            } else switch (kind) {
                case 1: switch (order) {
                    case 0: rv.dvalue = gsl_sf_bessel_J0(funcargs[0].dvalue); break;
                    case 1: rv.dvalue = gsl_sf_bessel_J1(funcargs[0].dvalue); break;
                    default: rv.dvalue = gsl_sf_bessel_Jn(order, funcargs[0].dvalue); break;
                }
                    break;
                case 2: switch (order) {
                    case 0: rv.dvalue = gsl_sf_bessel_Y0(funcargs[0].dvalue); break;
                    case 1: rv.dvalue = gsl_sf_bessel_Y1(funcargs[0].dvalue); break;
                    default: rv.dvalue = gsl_sf_bessel_Yn(order, funcargs[0].dvalue); break;
                }
                    break;
                default: success = 0; break;
            }
            }
            break;

/************************
 ***      int         ***
 ************************/
        case 19:
            rv.type = typeCon;
            if (funcargs[0].type == typeStr) {
                rv.lvalue = (long)funcargs[0].svalue->toDouble();
            } else {
                rv.lvalue = (long)funcargs[0].dvalue;
            }
            break;

/************************
 ***      round       ***
 ************************/
        case 20:
            rv.type = typeCon;
            rv.lvalue = (long)(nint(funcargs[0].dvalue));
            break;

/************************
 ***      frac        ***
 ************************/
        case 21:
            rv.dvalue = fabs(funcargs[0].dvalue - (double)(int)funcargs[0].dvalue);
            break;

/************************
 ***      abs         ***
 ************************/
        case 22:
            if (rv.type == typeDbl) rv.dvalue = fabs(funcargs[0].dvalue);
            else if (rv.type == typeCom) {
                rv.type = typeDbl;
                rv.dvalue = complex_abs(*funcargs[0].cvalue);
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) {
                    rv.fvalue->Abs();
                }
            } else {
                dp_output("%s: ", funcs[id].name.c_str());
                yyerror("Invalid argument");
                success = 0;
            }
            break;

/************************
 ***      sign        ***
 ************************/
        case 23:
            rv.type = typeCon;
            rv.lvalue = (funcargs[0].dvalue < 0.0 ? -1 : 1);
            break;

/************************
 ***     rad2deg      ***
 ************************/
        case 24:
            if (rv.type == typeDbl) rv.dvalue = funcargs[0].dvalue * 180.0 / M_PI;
            else if (rv.type == typeCom) rv.cvalue = CreateComplex(*funcargs[0].cvalue * 180.0 / M_PI);
            else if (rv.type == typeFits) {
                rv.clone(funcargs[0]);
                if (success) *rv.fvalue *= 180.0 / M_PI;
            }
            break;

/************************
 ***     deg2rad      ***
 ************************/
        case 25:
            if (rv.type == typeDbl) rv.dvalue = funcargs[0].dvalue / 180.0 * M_PI;
            else if (rv.type == typeCom) rv.cvalue = CreateComplex(*funcargs[0].cvalue / 180.0 * M_PI);
            else if (rv.type == typeFits) {
                rv.clone(funcargs[0]);
                if (success) *rv.fvalue *= M_PI / 180.0;
            }
            break;

/************************
 ***      float       ***
 ************************/
        case 26:
            rv.type = typeDbl;
            if (funcargs[0].type == typeStr) {
                rv.dvalue = atof(funcargs[0].svalue->c_str());
            } else if (funcargs[0].type == typeCon) {
                rv.dvalue = (double)funcargs[0].lvalue;
            } else if (funcargs[0].type == typeCom) {
                rv.dvalue = real(*funcargs[0].cvalue);
            } else if (funcargs[0].type == typeDbl) {
                rv.dvalue = funcargs[0].dvalue;
            } else if (funcargs[0].type == typeFits) {
                rv.clone(funcargs[0]);
                rv.fvalue->setType(R4);
            } else {
                rv.dvalue = 0.0;
            }
            break;

/************************
 ***     strlen       ***
 ************************/
        case 27:
            rv.type = typeCon;
            rv.lvalue = funcargs[0].svalue->length();
            break;

/************************
 ***      min         ***
 ************************/
        case 28:
            if (funcargs[0].type == typeFits && function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_min(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_min(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (nargs == 1) {
                    if (funcargs[0].type == typeDbl) {
                        rv.dvalue = funcargs[0].dvalue;
                    } else {
                        rv.dvalue = dp_min(*funcargs[0].fvalue);
                    }
                } else {
                    if (funcargs[0].type == typeDbl) {
                        rv.dvalue = (funcargs[0].dvalue < funcargs[1].dvalue ? funcargs[0].dvalue : funcargs[1].dvalue);
                    } else {
                        rv.dvalue = dp_min_i(*funcargs[0].fvalue, funcargs[1].dvalue);
                    }
                }
            }
//            rv.dvalue = funcargs[0].fvalue->get_min();
            break;

/************************
 ***      max         ***
 ************************/
        case 29:
            if (funcargs[0].type == typeFits && function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_max(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_max(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (nargs == 1) {
                    if (funcargs[0].type == typeDbl) {
                        rv.dvalue = funcargs[0].dvalue;
                    } else {
                        rv.dvalue = dp_max(*funcargs[0].fvalue);
                    }
                } else {
                    if (funcargs[0].type == typeDbl) {
                        rv.dvalue = (funcargs[0].dvalue > funcargs[1].dvalue ? funcargs[0].dvalue : funcargs[1].dvalue);
                    } else {
                        rv.dvalue = dp_max_i(*funcargs[0].fvalue, funcargs[1].dvalue);
                    }
                }
            }
//          rv.dvalue = funcargs[0].fvalue->get_max();
            break;

/************************
 ***      avg         ***
 ************************/
        case 30:
            if (function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_average(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_average(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (nargs == 1) rv.dvalue = dp_avg(*funcargs[0].fvalue);
                else rv.dvalue = dp_avg_i(*funcargs[0].fvalue, funcargs[1].dvalue);
            }
//          if (nargs == 1) rv.dvalue = funcargs[0].fvalue->get_avg();
//          else rv.dvalue = funcargs[0].fvalue->get_avg(funcargs[1].dvalue);
            break;

/************************
 ***      total       ***
 ************************/
        case 31:
            if (funcargs[0].type == typeFits && function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (funcargs[0].type != typeFits) {
                    rv.dvalue = funcargs[0].dvalue;
                } else {
                    if (nargs == 1) rv.dvalue = dp_total(*funcargs[0].fvalue);
                    else rv.dvalue = dp_total_i(*funcargs[0].fvalue, funcargs[1].dvalue);
                }
            }
//          rv.dvalue = funcargs[0].fvalue->get_flux();
            break;

/************************
 ***     median       ***
 ************************/
        case 32:
            if (funcargs[0].type == typeFits && function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_median(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_median(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (nargs == 1) rv.dvalue = funcargs[0].fvalue->get_median();
                else rv.dvalue = funcargs[0].fvalue->get_median(funcargs[1].dvalue);
            }
            break;

/************************
 ***      naxis       ***
 ************************/
        case 33:
            rv.type = typeCon;
            if (funcargs[0].type == typeFits) {
                rv.lvalue = funcargs[0].fvalue->Naxis(0);
            } else if (funcargs[0].type == typeFitsFile) {
                int retint;
                int extension = 0;
                Fits *fvalue;

                if (nargs == 2) extension = funcargs[1].lvalue;
                fvalue = CreateFits();
                success = fvalue->OpenFITS(funcargs[0].ffvalue->c_str());
                if (success) {
                    if (extension < 1) {
                        success = (fvalue->hdr = fvalue->ReadFitsHeader() >= 0);
                    } else {
                        success = (fvalue->hdr = fvalue->ReadFitsExtensionHeader(extension) >= 0);
                    }
                    fvalue->CloseFITS();
                }
                if (!success) break;
                if (fvalue->GetIntKey("NAXIS", &retint)) {
                    rv.lvalue = (long)retint;
                }
            } else {
                rv.lvalue = 1;
            }
            break;

/************************
 ***     naxis1       ***
 ************************/
        case 34:
            rv.type = typeCon;
            if (funcargs[0].type == typeFits) {
                rv.lvalue = funcargs[0].fvalue->Naxis(1);
            } else if (funcargs[0].type == typeFitsFile) {
                int retint;
                int extension = 0;
                Fits *fvalue;

                if (nargs == 2) extension = funcargs[1].lvalue;
                fvalue = CreateFits();
                success = fvalue->OpenFITS(funcargs[0].ffvalue->c_str());
                if (success) {
                    if (extension < 1) {
                        success = (fvalue->hdr = fvalue->ReadFitsHeader() >= 0);
                    } else {
                        success = (fvalue->hdr = fvalue->ReadFitsExtensionHeader(extension) >= 0);
                    }
                    fvalue->CloseFITS();
                }
                if (!success) break;
                if (fvalue->GetIntKey("NAXIS1", &retint)) {
                    rv.lvalue = (long)retint;
                }
            } else {
                rv.lvalue = 1;
            }
            break;

/************************
 ***     naxis2       ***
 ************************/
        case 35:
            rv.type = typeCon;
            if (funcargs[0].type == typeFits) {
                rv.lvalue = funcargs[0].fvalue->Naxis(2);
            } else if (funcargs[0].type == typeFitsFile) {
                int retint;
                int extension = 0;
                Fits *fvalue;

                if (nargs == 2) extension = funcargs[1].lvalue;
                fvalue = CreateFits();
                success = fvalue->OpenFITS(funcargs[0].ffvalue->c_str());
                if (success) {
                    if (extension < 1) {
                        success = (fvalue->hdr = fvalue->ReadFitsHeader() >= 0);
                    } else {
                        success = (fvalue->hdr = fvalue->ReadFitsExtensionHeader(extension) >= 0);
                    }
                    fvalue->CloseFITS();
                }
                if (!success) break;
                if (fvalue->GetIntKey("NAXIS2", &retint)) {
                    rv.lvalue = (long)retint;
                }
            } else {
                rv.lvalue = 1;
            }
            break;

/************************
 ***     naxis3       ***
 ************************/
        case 36:
            rv.type = typeCon;
            if (funcargs[0].type == typeFits) {
                rv.lvalue = funcargs[0].fvalue->Naxis(3);
            } else if (funcargs[0].type == typeFitsFile) {
                int retint;
                int extension = 0;
                Fits *fvalue;

                if (nargs == 2) extension = funcargs[1].lvalue;
                fvalue = CreateFits();
                success = fvalue->OpenFITS(funcargs[0].ffvalue->c_str());
                if (success) {
                    if (extension < 1) {
                        success = (fvalue->hdr = fvalue->ReadFitsHeader() >= 0);
                    } else {
                        success = (fvalue->hdr = fvalue->ReadFitsExtensionHeader(extension) >= 0);
                    }
                    fvalue->CloseFITS();
                }
                if (!success) break;
                if (fvalue->GetIntKey("NAXIS3", &retint)) {
                    rv.lvalue = (long)retint;
                }
            } else {
                rv.lvalue = 1;
            }
            break;

/************************
 ***      xmax        ***
 ************************/
        case 37: {
            int x, y;

            rv.type = typeCon;
            funcargs[0].fvalue->max_pos(&x, &y);
            rv.lvalue = x;
            }
            break;

/************************
 ***      ymax        ***
 ************************/
        case 38: {
            int x, y;

            rv.type = typeCon;
            funcargs[0].fvalue->max_pos(&x, &y);
            rv.lvalue = y;
            }
            break;

/************************
 ***      xcen        ***
 ************************/
        case 39: {
            double x, y;

            rv.type = typeDbl;
            funcargs[0].fvalue->centroid(&x, &y);
            rv.dvalue = x;
            }
            break;

/************************
 ***      ycen        ***
 ************************/
        case 40: {
            double x, y;

            rv.type = typeDbl;
            funcargs[0].fvalue->centroid(&x, &y);
            rv.dvalue = y;
            }
            break;

/************************
 ***      real        ***
 ************************/
        case 41:
            if (rv.type == typeDbl) rv.dvalue = funcargs[0].dvalue;
            else if (rv.type == typeCom) {
                rv.type = typeDbl;
                rv.dvalue = funcargs[0].cvalue->real();
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else {
                    rv.fvalue = funcargs[0].fvalue;
                }
                rv.fvalue->ri_r();
            }
            break;

/************************
 ***      imag        ***
 ************************/
        case 42:
            if (rv.type == typeDbl) rv.dvalue = 0.0;
            else if (rv.type == typeCom) {
                rv.type = typeDbl;
                rv.dvalue = funcargs[0].cvalue->imag();
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else {
                    rv.fvalue = funcargs[0].fvalue;
                }
                rv.fvalue->ri_i();
            }
            break;

/************************
 ***      arg         ***
 ************************/
        case 43:
            if (rv.type == typeDbl) rv.dvalue = complex_arg(dpComplex(funcargs[0].dvalue));
            else if (rv.type == typeCom) {
                rv.type = typeDbl;
                rv.dvalue = complex_arg(*funcargs[0].cvalue);
            } else if (rv.type == typeFits) {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else {
                    rv.fvalue = funcargs[0].fvalue;
                }
                rv.fvalue->ri_arg();
            }
            break;

/********************************************
 ***      jd, jdnumber, jdfraction, mjd   ***
 ********************************************/
        case 44:
        case 46: rv.type = typeDbl;
        case 45: {
                CJulianDay jd;

                if (nargs == 3) jd.SetJD(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue, 0, 0, 0.0);
                else if (nargs == 4) jd.SetJD(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue, 0, 0.0);
                else if (nargs == 5) jd.SetJD(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, 0.0);
                else {
                    if (funcargs[5].type == typeCon) funcargs[5].dvalue = (double)funcargs[5].lvalue;
                    jd.SetJD(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, funcargs[5].dvalue);
                }
                if (id + 1 == 44) {
                    rv.dvalue = (double)jd;
                } else if (id + 1== 45) {
                    rv.type = typeCon;
                    rv.lvalue = jd.GetNumber();
                }
                else rv.dvalue = jd.GetFraction();
            }
            break;

/************************
 ***      upper       ***
 ************************/
        case 47:
            rv.svalue = CreateString(funcargs[0].svalue->upper());
            break;

/************************
 ***      lower       ***
 ************************/
        case 48:
            rv.svalue = CreateString(funcargs[0].svalue->lower());
            break;

/************************
 ***     string       ***
 ************************/
        case 49:
            rv.type = typeStr;
            if ((function_options != 0) && (funcargs[0].type != typeCom)) {
                double value = funcargs[0].dvalue;
                int hour, minute;
                double seconds;

                if (function_options == 4) value *= 180.0 / M_PI;
                seconds = value;
                hour = (int)seconds;
                seconds = (seconds - hour) * 60.0;
                minute = (int)seconds;
                seconds = (seconds - minute) * 60.0;
                rv.svalue = CreateString();
                switch (function_options) {
                    case 1:
                        rv.svalue->sprintf("%02i:%02i:%06.3f", hour, minute, seconds);
                        break;
                    case 2:
                    case 4:
                        rv.svalue->sprintf("%id%02i'%06.3f\"", hour, minute, seconds);
                        break;
                    default: break;
                }
            } else if ((funcargs[0].type == typeDbl) && ((double)funcargs[0].lvalue == funcargs[0].dvalue)) {
                rv.svalue = CreateString(funcargs[0].lvalue);
            } else if (funcargs[0].type == typeDbl) {
                rv.svalue = CreateString(funcargs[0].dvalue);
            } else if (funcargs[0].type == typeStr) {
                rv.svalue = CreateString(*funcargs[0].svalue);
            } else {
                rv.svalue = CreateString(*funcargs[0].cvalue);
            }
            break;

/************************
 ***     calday       ***
 ************************/
        case 50: {
            char _tmp[256];
            CJulianDay jd(funcargs[0].dvalue);
            if (nargs == 2) jd = CJulianDay((long)funcargs[0].dvalue, funcargs[1].dvalue);
            if (function_options & 1) {
                JDStruct mjdbase;
                mjdbase.dFraction = 0.5;
                mjdbase.lNumber = 2400000;
                jd += mjdbase;
            }

            rv.type = typeStr;
            rv.svalue = CreateString(jd.GetUTCString(_tmp, 255));
            }
            break;

/************************
 ***     header       ***
 ************************/
        case 51:
            rv.type = typeStr;
            if (funcargs[0].type == typeFitsFile) {
                int extension = 0;
                if (nargs == 2) extension = funcargs[1].lvalue;
                funcargs[0].fvalue = CreateFits();
                if (funcargs[0].fvalue->OpenFITS(funcargs[0].ffvalue->c_str())) {
                    if (extension < 1) {
                        if (funcargs[0].fvalue->ReadFitsHeader() >= 0) {
//                            funcargs[0].fvalue->CloseFITS();
                        }
                    } else {
                        if (funcargs[0].fvalue->ReadFitsExtensionHeader(extension) >= 0) {
//                            funcargs[0].fvalue->CloseFITS();
                        }
                    }
                    funcargs[0].fvalue->CloseFITS();
                }
                rv.svalue = CreateString(funcargs[0].fvalue->GetHeader());
            } else if (funcargs[0].type == typeFits) {
                funcargs[0].fvalue->updateHeader();
                rv.svalue = CreateString(funcargs[0].fvalue->GetHeader());
            }
            else success = 0;
            break;

/************************
 ***    dayofweek     ***
 ************************/
        case 52:
            rv.type = typeStr;
            if (nargs == 1) rv.svalue = CreateString(CJulianDay(funcargs[0].dvalue).GetDayOfWeekString());
            else if (nargs == 2) rv.svalue = CreateString(CJulianDay((long)funcargs[0].dvalue, funcargs[1].dvalue).GetDayOfWeekString());
            else rv.svalue = CreateString(CJulianDay((USHORT)funcargs[0].dvalue, (USHORT)funcargs[1].dvalue, funcargs[2].lvalue).GetDayOfWeekString());
            break;

/************************
 ***      fits        ***
 ************************/
        case 53:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 1) {
                if ((funcargs[0].type == typeCon) || (funcargs[0].type == typeDbl)) {
                    if (funcargs[0].lvalue < 1) {
                        success = FALSE;
                    } else {
                        success = rv.fvalue->create(funcargs[0].lvalue, 1);
                    }
                } else {
                    rv.type = typeFitsFile;
                    rv.ffvalue = CreateString(*funcargs[0].svalue);
                }
            } else if (nargs == 2) {
                if ((funcargs[0].lvalue < 1) || (funcargs[1].lvalue < 1)) success = FALSE;
                else success = rv.fvalue->create(funcargs[0].lvalue, funcargs[1].lvalue);
            } else {
                if ((funcargs[0].lvalue < 1) || (funcargs[1].lvalue < 1) || (funcargs[2].lvalue < 1)) success = FALSE;
                else success = rv.fvalue->create(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue);
            }
            break;

/************************
 ***      gauss       ***
 ************************/
        case 54:
            if (nargs == 1) {
                if (rv.type == typeDbl) {
                    rv.dvalue = exp(-FOUR_LN2 * funcargs[0].dvalue * funcargs[0].dvalue);
                } else if (rv.type == typeFits) {
                    rv.clone(funcargs[0]);
                    if (success) {
                        rv.fvalue->setType(R8);
                        for (long n = 0; n < rv.fvalue->Nelements(); n++) rv.fvalue->r8data[n] = exp(-FOUR_LN2 * rv.fvalue->r8data[n] * rv.fvalue->r8data[n]);
                    }
                }
            } else {
                if (nargs < 3) funcargs[2].dvalue = 1.0;
                rv.type = typeFits;
                rv.fvalue = CreateFits();
                if (nargs == 3) success = rv.fvalue->gauss(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue);
                else if (nargs == 4) success = rv.fvalue->gauss(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
                else success = rv.fvalue->gauss(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue, funcargs[4].dvalue);
                dpuser_vars["naxis1"].lvalue = onaxis1;
                dpuser_vars["naxis2"].lvalue = onaxis2;
            }
            break;

/************************
 ***     circle       ***
 ************************/
        case 55:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->circle(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***     ellipse      ***
 ************************/
        case 56:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 3) success = rv.fvalue->ellipse(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[2].dvalue, 0.0);
            else if (nargs == 4) success = rv.fvalue->ellipse(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue, 0.0);
            else success = rv.fvalue->ellipse(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue, funcargs[4].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***      rect        ***
 ************************/
        case 57:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->rect(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, (int)funcargs[0].dvalue, (int)funcargs[1].dvalue, (int)funcargs[2].dvalue, (int)funcargs[3].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***      delta       ***
 ************************/
        case 58:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->delta(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, (int)funcargs[0].dvalue, (int)funcargs[1].dvalue);
            if (success) if (nargs == 3) *rv.fvalue *= funcargs[2].dvalue;
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***     cosbell      ***
 ************************/
        case 59:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->cosbell(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***     chinhat      ***
 ************************/
        case 60:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->chinese_hat(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***      airy        ***
 ************************/
        case 61:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 3) {
                success = rv.fvalue->airy(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, 0.0);
            } else {
                success = rv.fvalue->airy(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            }
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***    cubemedian    ***
 ************************/
        case 62:
            if (rv.type == typeFits) {
                rv.fvalue = CreateFits();
                if (nargs == 2) success = rv.fvalue->CubeMedian(*funcargs[0].fvalue, funcargs[1].dvalue);
                else success = rv.fvalue->CubeMedian(*funcargs[0].fvalue);
            } else {
                rv.type = typeFits;
                rv.fvalue = CreateFits();
                if (nargs < 3) optArgI[2] = 0; else optArgI[2] = funcargs[2].lvalue;
                if (nargs < 2) optArgI[1] = 1; else optArgI[1] = funcargs[1].lvalue;
                if (nargs == 2)
                    success = rv.fvalue->CubeMedian(funcargs[0].ffvalue->c_str(), funcargs[1].dvalue);
                else {
                    success = rv.fvalue->CubeMedian(funcargs[0].ffvalue->c_str(), optArgI[1], optArgI[2]);
                }
            }
            break;

/************************
 ***     cubeavg      ***
 ************************/
        case 63: {
            bool reject = FALSE;

            rv.fvalue = CreateFits();
            if (nargs == 2) reject = TRUE;
            if (nargs < 3) optArgI[2] = 0; else optArgI[2] = funcargs[2].lvalue;
            if (nargs < 2) optArgI[1] = 1; else optArgI[1] = funcargs[1].lvalue;
            if (rv.type == typeFits) {
                if (reject)
                    success = cube_avg(*funcargs[0].fvalue, *rv.fvalue, funcargs[1].dvalue);
                else
                    success = cube_avg(*funcargs[0].fvalue, *rv.fvalue, optArgI[1], optArgI[2]);
            } else if (rv.type == typeFitsFile) {
                rv.type = typeFits;
                if (reject)
                    success = cube_avg(funcargs[0].ffvalue->c_str(), *rv.fvalue, funcargs[1].dvalue);
                else
                    success = cube_avg(funcargs[0].ffvalue->c_str(), *rv.fvalue, optArgI[1], optArgI[2]);
            } else {
                rv.type = typeFits;
                success = CubeAverage(*rv.fvalue, *funcargs[0].arrvalue);
            }
            }
            break;

/************************
 ***      ssa         ***
 ************************/
        case 64:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (funcargs[0].type == typeFitsFile) {
                if (nargs == 7) success = rv.fvalue->qssa(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, 0, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
                else success = rv.fvalue->qssa(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[7].lvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
            } else if (funcargs[0].type == typeStrarr) {
                int resize;

                if (function_options == 1) resize = 1;
                else resize = 0;
                if (nargs == 7) qssa(*rv.fvalue, *funcargs[0].arrvalue, funcargs[1].lvalue, funcargs[2].lvalue, 0, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue, resize);
                else qssa(*rv.fvalue, *funcargs[0].arrvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[7].lvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue, resize);
            } else {
                if (nargs == 7) rv.fvalue->qssa(*funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, 0, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
                else rv.fvalue->qssa(*funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[7].lvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
            }
            break;

/************************
 ***      mosaic      ***
 ************************/
        case 65:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (funcargs[0].type == typeStr) {
                success = rv.fvalue->mosaic(funcargs[0].svalue->c_str());
            } else {
                if (nargs == 3) {
                    float *data1 = floatdata(*funcargs[1].fvalue);
                    float *data2 = floatdata(*funcargs[2].fvalue);
                    if (data1 && data2)
                        success = mosaic(*rv.fvalue, *funcargs[0].arrvalue, data1, data2);
                    if (data1 && (data1 != funcargs[1].fvalue->r4data)) free(data1);
                    if (data2 && (data2 != funcargs[2].fvalue->r4data)) free(data2);
                } else if (nargs == 4) {
                    float *data1 = floatdata(*funcargs[1].fvalue);
                    float *data2 = floatdata(*funcargs[2].fvalue);
                    float *data3 = floatdata(*funcargs[3].fvalue);
                    if (data1 && data2 && data3)
                        success = mosaic(*rv.fvalue, *funcargs[0].arrvalue, data1, data2, data3);
                    if (data1 && (data1 != funcargs[1].fvalue->r4data)) free(data1);
                    if (data2 && (data2 != funcargs[2].fvalue->r4data)) free(data2);
                    if (data3 && (data3 != funcargs[3].fvalue->r4data)) free(data3);
                } else success = FALSE;
            }
            break;

/************************
 ***      shift       ***
 ************************/
        case 66:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else {
                rv.fvalue = funcargs[0].fvalue;
            }
            if (success) {
                bool fs = TRUE;

                if (nargs == 3) {
                    if ((funcargs[1].dvalue == (double)(int)funcargs[1].dvalue) &&
                        (funcargs[2].dvalue == (double)(int)funcargs[2].dvalue))
                        fs = FALSE;
                } else {
                    if ((funcargs[1].dvalue == (double)(int)funcargs[1].dvalue) &&
                        (funcargs[2].dvalue == (double)(int)funcargs[2].dvalue) &&
                        (funcargs[3].dvalue == (double)(int)funcargs[3].dvalue))
                        fs = FALSE;
                }
                if (fs) {
                    // sub-pixel shift
                    int method = 0;

                    if (function_options & 2) method = 0; // linear
                    else if (function_options & 4) method = 1; // fft
                    else if (function_options & 8) method = 3; // poly3
                    if (nargs == 3) {
                        success = rv.fvalue->fshift(funcargs[1].dvalue, funcargs[2].dvalue, method);
                    } else {
                        success = rv.fvalue->fshift(funcargs[1].dvalue, funcargs[2].dvalue, (int)funcargs[3].dvalue);
                    }
                } else {
                    // pixel shift
                    int x, y, z = 0;

                    x = (int)funcargs[1].dvalue;
                    y = (int)funcargs[2].dvalue;
                    if (nargs == 4)
                        z = (int)funcargs[3].dvalue;
                    if (function_options == 1)
                        success = rv.fvalue->wrap(x, y, z);
                    else
                        success = rv.fvalue->ishift(x, y, z);
                }
            }
            break;

/************************
 ***     rotate       ***
 ************************/
        case 67:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 2) success = rv.fvalue->rotate(funcargs[1].dvalue);
                else if (nargs == 3) success = rv.fvalue->rotate(funcargs[1].dvalue, funcargs[2].dvalue);
                else success = rv.fvalue->rotate(funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            }
            break;

/************************
 ***      fft         ***
 ************************/
        case 68:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = rv.fvalue->fft();
            break;

/************************
 ***      reass       ***
 ************************/
        case 69:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = rv.fvalue->reass();
            break;

/************************
 ***      norm        ***
 ************************/
        case 70:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (function_options & 2) rv.fvalue->norf(0);
                else if (function_options & 4) rv.fvalue->norf(1);
                else rv.fvalue->norm();
            }
            break;

/************************
 ***      clip        ***
 ************************/
        case 71:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 3) success = rv.fvalue->clip(funcargs[1].dvalue, funcargs[2].dvalue);
                else success = rv.fvalue->inclip(funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            }
            break;

/************************
 ***     smooth       ***
 ************************/
        case 72:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;

            if (success) {
                if ((function_options & 2) && (rv.fvalue->Naxis(3) > 1)) {
                    rv.fvalue->smooth1d(funcargs[1].dvalue, 3);
                } else if (function_options & 4) {
                    rv.fvalue->smooth1d(funcargs[1].dvalue, 1);
                } else if (function_options & 8) {
                    rv.fvalue->smooth1d(funcargs[1].dvalue, 2);
                } else {
                    success = rv.fvalue->smooth(funcargs[1].dvalue);
                }
            }
            break;

/************************
 ***     boxcar       ***
 ************************/
        case 73:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                int method = 0;
                int method2 = 0;

                if (function_options & 2) method = 1;
                else if (function_options & 4) method = 2;
                else if (function_options & 8) method = 3;

                if (function_options & 32) method2 = 1;
                else if (function_options & 64) method2 = 2;
                else if (function_options & 128) method2 = 3;

                success = Boxcar(*rv.fvalue, funcargs[1].lvalue, method, method2);

            }
            break;

/************************
 ***     3dexpand     ***
 ************************/
        case 78:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = expandCal3d(*rv.fvalue);
            break;

/************************
 ***    dpixcreate    ***
 ************************/
        case 79:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 2) success = rv.fvalue->dpixCreate(funcargs[1].dvalue);
                else if (nargs == 3) success = rv.fvalue->dpixCreate(funcargs[1].dvalue, funcargs[2].lvalue);
                else success = rv.fvalue->dpixCreate(funcargs[1].dvalue, funcargs[2].lvalue, funcargs[3].lvalue);
            }
            break;

/************************
 ***     dpixapply    ***
 ************************/
        case 80:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;

            if (success) {
                if (function_options & 1) {
                    Fits cube, dplcube;

                    if (!spifficube(*funcargs[0].fvalue, cube, 1)) {
                        success = FALSE;
                        break;
                    }
                    if (!spifficube(*funcargs[1].fvalue, dplcube, 1)) {
                        success = FALSE;
                        break;
                    }
                    if (function_options & 2) {
                        if (nargs == 2) success = DeadpixApply(cube, dplcube, 3);
                        else if (nargs == 3) success = DeadpixApply(cube, dplcube, 3, funcargs[2].lvalue);
                    } else {
                        if (nargs == 2) success = DeadpixApply(cube, dplcube, dpuser_vars["method"].lvalue);
                        else if (nargs == 3) success = DeadpixApply(cube, dplcube, dpuser_vars["method"].lvalue, funcargs[2].lvalue);
                    }
                    if (success) {
                        success = spiffiuncube(cube, *rv.fvalue, 1);
                    }
                } else {
                    if (nargs == 2) success = DeadpixApply(*rv.fvalue, *funcargs[1].fvalue, dpuser_vars["method"].lvalue);
                    else if (nargs == 3) success = DeadpixApply(*rv.fvalue, *funcargs[1].fvalue, dpuser_vars["method"].lvalue, funcargs[2].lvalue);
                    else success = DeadpixApply(*rv.fvalue, *funcargs[1].fvalue, dpuser_vars["method"].lvalue, funcargs[2].lvalue);
                }
            }
            dpuser_vars["method"].lvalue = omethod;
            break;

/************************
 ***      flip        ***
 ************************/
        case 81:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = rv.fvalue->flip(funcargs[1].lvalue);
            break;

/************************
 ***     enlarge      ***
 ************************/
        case 82:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 2) success = rv.fvalue->enlarge(funcargs[1].lvalue);
                else success = rv.fvalue->enlarge(funcargs[1].lvalue, funcargs[2].lvalue);
            }
            break;

/************************
 ***     resize       ***
 ************************/
        case 83:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 3) success = rv.fvalue->resize(funcargs[1].lvalue, funcargs[2].lvalue);
                else success = rv.fvalue->resize(funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue);
            }
            break;

/************************
 ***      wien        ***
 ************************/
        case 84:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (function_options == 1) {
                    if (nargs == 2) success = rv.fvalue->wien(*funcargs[1].fvalue);
                    else success = rv.fvalue->wien(*funcargs[1].fvalue, funcargs[2].dvalue);
                } else {
                    if (nargs == 2) success = rv.fvalue->quick_wien(*funcargs[1].fvalue);
                    else success = rv.fvalue->quick_wien(*funcargs[1].fvalue, funcargs[2].dvalue);
                }
            }
            break;

/************************
 ***      lucy        ***
 ************************/
        case 85:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (function_options == 1) {
                    if (nargs == 3) success = rv.fvalue->lucy(*funcargs[1].fvalue, funcargs[2].lvalue);
                    else success = rv.fvalue->lucy(*funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].dvalue);
                } else {
                    if (nargs == 3) success = rv.fvalue->quick_lucy(*funcargs[1].fvalue, funcargs[2].lvalue);
                    else success = rv.fvalue->quick_lucy(*funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].dvalue);
                }
            }
            break;

/************************
 ***      center      ***
 ************************/
        case 86: {
            int x, y;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                rv.fvalue->max_pos(&x, &y);
                success = rv.fvalue->shift(rv.fvalue->Naxis(1) / 2 + 1 - x, rv.fvalue->Naxis(2) / 2 + 1 - y, 2);
            }
            }
            break;

/************************
 ***      3dnorm      ***
 ************************/
        case 87:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = norm3d(*rv.fvalue, funcargs[1].svalue->c_str());
            break;

/************************
 ***      conj        ***
 ************************/
        case 88:
            if (rv.type == typeCom) rv.cvalue = CreateComplex(complex_conj(*funcargs[0].cvalue));
            else {
                if (isVariable(funcargs[0].fvalue) == 1) {
                    rv.fvalue = CreateFits();
                    success = rv.fvalue->copy(*funcargs[0].fvalue);
                } else
                    rv.fvalue = funcargs[0].fvalue;
                if (success) rv.fvalue->conj();
            }
            break;

/************************
 ***     correl       ***
 ************************/
        case 89:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (function_options == 1) {
                    success = rv.fvalue->correl_real(*funcargs[1].fvalue);
                } else {
                    success = rv.fvalue->correl(*funcargs[1].fvalue);
                }
            }
            break;

/************************
 ***     readfits     ***
 ************************/
        case 90: {
            int i, j;
            int x[6] = { 0, 0, 0, 0, 0, 0 };

            for (i = 1, j = 0; i < nargs; i++, j++) x[j] = funcargs[i].lvalue;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->ReadFITS(funcargs[0].svalue->c_str(), x[0], x[1], x[2], x[3], x[4], x[5]);
#ifdef DPQT
            if (!success) {
                QImage newimage;
                if (newimage.load(QString((*funcargs[0].svalue).c_str()))) {
                    int x, y, n = 0;

                    rv.fvalue->create(newimage.height(), newimage.width(), I1);
                    for (x = 0; x < newimage.width(); x++) {
                        for (y = 0; y < newimage.height(); y++) {
                            rv.fvalue->i1data[n++] = qGray(newimage.pixel(x, y));
                        }
                    }
                    rv.fvalue->rot90(90);
                    success = TRUE;
                }
            }
#endif
            }
            break;

/************************
 ***     3dspec       ***
 ************************/
        case 91: {
            int i;
            Fits _tmp;
            int method = 0;

            rv.fvalue = CreateFits();
            success = rv.fvalue->create(funcargs[0].fvalue->Naxis(3), 1);
            if (success) {
                switch (function_options) {
                    case 1: method = 0; break;
                    case 2: method = 1; break;
                    case 4: method = 2; break;
                    default: break;
                }

                if (funcargs[1].type == typeFits) {
                    // do this so the header is up-to-date
                    rv.fvalue->spec3d(*funcargs[0].fvalue, 1, 1, 0, 0);
                    for (i = 1; i <= funcargs[0].fvalue->Naxis(3); i++) {
                        funcargs[0].fvalue->extractRange(_tmp, -1, -1, -1, -1, i, i);
                        _tmp *= *funcargs[1].fvalue;
                        switch (method) {
                            case 0:
                                rv.fvalue->r4data[i-1] = _tmp.get_flux();
                                break;
                            case 1:
                                rv.fvalue->r4data[i-1] = _tmp.get_avg();
                                break;
                            case 2:
                                rv.fvalue->r4data[i-1] = _tmp.get_median();
                                break;
                            default:
                                break;
                        }
                    }
                } else {
                    switch (nargs) {
                        case 3:
                            rv.fvalue->spec3d(*funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, 0, 0);
                            break;
                        case 4:
                            rv.fvalue->spec3d(*funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue, 0, method);
                            break;
                        case 5:
                            rv.fvalue->spec3d(*funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, method);
                            break;
                        default: break;
                    }
                }
            }
            }
            break;

/************************
 ***     stddev       ***
 ************************/
        case 92:
            if (function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_stddev(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_stddev(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;

                if (nargs == 1) rv.dvalue = funcargs[0].fvalue->get_stddev();
                else rv.dvalue = funcargs[0].fvalue->get_stddev(funcargs[1].dvalue);
            }
            break;

/************************
 ***     variance     ***
 ************************/
        case 93:
            if (function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_variance(*funcargs[0].fvalue, axis);
                else rv.fvalue->collapse_variance(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                if (nargs == 1) rv.dvalue = funcargs[0].fvalue->get_variance();
                else rv.dvalue = funcargs[0].fvalue->get_variance(funcargs[1].dvalue);
            }
            break;

/************************
 ***     meddev       ***
 ************************/
        case 94:
            if (funcargs[0].type == typeFits && function_options != 0) {
                int axis = 3;

                rv.fvalue = CreateFits();
                switch (function_options) {
                    case 1: axis = 1; break;
                    case 2: axis = 2; break;
                    case 4: axis = 3; break;
                    case 8: axis = 12; break;
                    case 16: axis = 23; break;
                    case 32: axis = 13; break;
                    default: break;
                }
                if (nargs == 1) rv.fvalue->collapse_meddev(*funcargs[0].fvalue, axis);
//                else rv.fvalue->collapse_median(*funcargs[0].fvalue, axis, funcargs[1].dvalue);
            } else {
                rv.type = typeDbl;
                rv.dvalue = funcargs[0].fvalue->get_meddev();
            }
            break;

/************************
 ***     saomark      ***
 ************************/
        case 95:
            if (ds9_running() == 0) {
                dp_output("ERROR: No ds9 is running! Please start first ds9 (at least v5.2)\n");
                success = false;
            }
            if (ds9_frame_loaded() == 0) {
                dp_output("ERROR: First load a fits-file into ds9 either in ds9 itself or with sao in dpuser!\n");
                success = false;
            }

            if (success) {
                int nx, ny, wcs = 0, pos, ret;
                dpString key, tmp;
                size_t lens[NXPA];
                char *bufs[NXPA];
                char *names[NXPA];
                char *messages[NXPA];

                // get size of displayed fits
                ret = XPAGet(xpa, xpaServer, (char *)"fits size", NULL,
                             bufs, lens, names, messages, NXPA);
                if (messages[0] == NULL) {
                    /* process buf contents */
                    tmp = bufs[0];
                    dpString sp = dpString(" ");
                    tmp = tmp.stripWhiteSpace();
                    nx = atoi(tmp.left(tmp.strpos(sp, false)).c_str());
                    ny = atoi(tmp.right(tmp.length() - tmp.strpos(sp, false)).c_str());
                    free(bufs[0]);
                } else {
                    /* error processing */
                    dp_output("ERROR: %s (%s)\n", messages[0], names[0]);
                    success = false;
                }
                if(names[0]) {
                    free(names[0]);
                }
                if(messages[0]) {
                    free(messages[0]);
                }

                if (success) {
                    // create fits of same size
                    dp_output("size: [%i, %i]\n", nx, ny);
                    rv.type = typeFits;
                    rv.fvalue = CreateFits();
                    if (!rv.fvalue->create(nx, ny)) {
                        dp_output("Failed creating return fits-array");
                        success = false;
                    }
                }

                if (success) {
                    dpString sp = dpString(" ");
                    key = "t";
                    while ((key != "q") && (xpa != NULL)) {

                        ret = XPAGet(xpa, xpaServer, (char *)"imexam key coordinate image", NULL,
                                     bufs, lens, names, messages, NXPA);

                        if( messages[0] == NULL ){
                            /* extract key and x/y-positions */
                            tmp = bufs[0];
                            tmp = tmp.stripWhiteSpace();
                            pos = tmp.strpos(sp, false);
                            key = tmp.left(pos);
                            tmp.remove(0,pos);
                            tmp = tmp.stripWhiteSpace();
                            nx = atoi(tmp.left(tmp.strpos(sp, false)).c_str());
                            ny = atoi(tmp.right(tmp.length() - tmp.strpos(sp, false)).c_str());
                            free(bufs[0]);

                            if (key != "d") {
                                if (key != "q") {
                                    // mark point
                                    tmp = "regions command { point " + dpString::number(nx) +
                                            " " + dpString::number(ny) + " }";
                                    ret = XPASet(xpa, xpaServer, (char*)tmp.c_str(), NULL,
                                                NULL, 0, names, messages, NXPA);

                                    // set positions in return value
                                    rv.fvalue->setValue(1.0, nx, ny);

                                    dp_output("marked [%d %d]\n", nx, ny);
                                }
                            } else {
                                // unmark point
                                ret = XPASet(xpa, xpaServer, (char *)"regions undo", NULL,
                                            NULL, 0, names, messages, NXPA);

                                rv.fvalue->setValue(0.0, nx, ny);

                                dp_output("unmarked [%d %d]\n", nx, ny);
                            }
                        } else {
                            /* error processing */
                            dp_output("ERROR: %s (%s)\n", messages[0], names[0]);
                        }
                        if(names[0])
                            free(names[0]);
                        if(messages[0])
                            free(messages[0]);
                    }
                }
            }
            break;

/************************
 ***     random       ***
 ************************/
        case 96: rv.type = typeDbl;
//          if (nargs == 1) idum = funcargs[0].lvalue;
//          rv.dvalue = ran1(&idum);
            if (nargs == 1) {
                const gsl_rng_type *T;

                gsl_rng_free(gsl_rng_r);
                gsl_rng_default_seed = funcargs[0].lvalue;
                T = gsl_rng_default;
                gsl_rng_r = gsl_rng_alloc(T);
            }
            rv.dvalue = gsl_rng_uniform(gsl_rng_r);
            break;

/************************
 ***     import       ***
 ************************/
        case 97: {
            char f;
            FILE *fd;
            dpStringList inp;
            dpString fl;
            char *newinput;
            dpint64 flength;

            if ((fd = fopen(funcargs[0].svalue->c_str(), "rb")) == NULL) {
                success = FALSE;
                dp_output("Could not open file %s for reading\n", funcargs[0].svalue->c_str());
                break;
            }
            fseek(fd, 0L, SEEK_END);
            flength = ftell(fd);
            rewind(fd);
            if ((newinput = (char *)calloc((flength+2), sizeof(char))) == NULL) {
                fclose(fd);
                success = FALSE;
                break;
            }
            fread(newinput, sizeof(char), flength, fd);
            dpString nnn = newinput;
/* T. Ott: Commented out - replaced by dpStringList::splitcrlf(nnn) for performance */
/*
            nnn.replace("\r\n", "\n");
            nnn.replace("\n\r", "\n");
            nnn.replace("\r", "\n");
            inp = dpStringList::split('\n', nnn);
*/
            inp = dpStringList::splitcrlf(nnn);
/*
            strcpy(newinput, "");
            if ((newinput = (char *)malloc(256 * sizeof(char))) == NULL) {
                fclose(fd);
                success = FALSE;
                break;
            }
            strcpy(newinput, "");
            irv = 0;
            while (irv != EOF) {
                l = s = 0;
                do {
                    irv = fscanf(fd, "%c", &newinput[l++]);
                    s++;
                    if (s == 255) {
                        if ((newinput = (char *)realloc(newinput, (l + 256) * sizeof(char))) == NULL) {
                            fclose(fd);
                            success = FALSE;
                            break;
                        }
                        s = 0;
                    }
                } while ((newinput[l-1] != '\n') && (irv != EOF));
                l--;
                while (((newinput[l] == '\n') || (newinput[l] == '\r')) && (l > -1)) l--;
                newinput[l+1] = (char)0;
                if (irv != EOF) {
                    inp.append(newinput);
                    free(newinput);
                    if ((newinput = (char *)malloc(256 * sizeof(char))) == NULL) {
                        fclose(fd);
                        success = FALSE;
                        break;
                    }
                    strcpy(newinput, "");
                    s = 0;
                }
            }
*/
            fclose(fd);
            free(newinput);
            int y = 0, x = 0, i, j, c = 0, cc = 0;
            if (!inp.empty()) {
                fl = inp[0];
                fl = fl.stripWhiteSpace();
                f = fl[0];

                if (function_options == 2) {

                    rv.type = typeStrarr;

                    rv.arrvalue = CreateStringArray(inp);

                } else if ((isdigit(f) != 0) || (f == '.') || (f == '-') || (function_options == 1)) {
                    dpStringList line;
                    rv.type = typeFits;
                    rv.fvalue = CreateFits();
                    char delimiter = ' ';
                    char comment;
                    char *end;
                    bool has_comment = FALSE;
                    int skip = 0;

                    if ((nargs >= 3) && (funcargs[2].svalue->size() == 1)) delimiter = funcargs[2].svalue->c_str()[0];
                    if ((nargs >= 4) && (funcargs[3].svalue->size() == 1)) {
                        comment = funcargs[3].svalue->c_str()[0];
                        has_comment = TRUE;
                    }
                    if ((nargs == 5) && (funcargs[4].lvalue > 0)) skip = funcargs[4].lvalue;
                    if ((nargs >= 2) && (funcargs[1].lvalue > 0)) {
                        x = funcargs[1].lvalue;
                    } else {
                        fl = inp[skip];
                        fl = fl.simplifyWhiteSpace();
                        x = fl.contains(delimiter) + 1;
                    }

                    y = inp.count();
                    dp_output("File is %i x %i\n", x, y);
                    if (!rv.fvalue->create(x, y, R8)) {
                        success = 0;
                        break;
                    }

                    dpProgress(-y, "");

                    for (i = skip; i < y; i++) {
                        dpProgress(i, "importing...");
                        c = rv.fvalue->C_I(0, cc);
                        fl = inp[i];
                        fl = fl.simplifyWhiteSpace();
                        if (has_comment && fl[0] == comment) fl = "";
                        line = dpStringList::split(delimiter, fl);
                        if (line.count() > 0) {
                            for (j = 0; j < x; j++) {
                                if (j < line.count()) {
                                    rv.fvalue->r8data[c] = strtod(line[j].c_str(), &end); //atof(line[j].c_str());
                                    if (end == line[j].c_str()) rv.fvalue->r8data[c] = std::numeric_limits<double>::quiet_NaN(); //0. / 0.;
                                } else {
                                    rv.fvalue->r8data[c] = std::numeric_limits<double>::quiet_NaN(); //0. / 0.;
                                }
                                c++;
                            }
                            cc++;
                        }
                    }
                    dpProgress(y, "");

                    if (cc != y) rv.fvalue->recreate(x, cc);

                } else {
                    rv.type = typeStrarr;
                    rv.arrvalue = CreateStringArray(inp);
                }
            } else {
                // input file was empty!
                rv.type = typeStrarr;
                rv.arrvalue = CreateStringArray();
            }
            }
            break;

/************************
 ***      rebin       ***
 ************************/
        case 98:
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 3) {
                    success = rv.fvalue->rebin(funcargs[1].lvalue, funcargs[2].lvalue);
                } else {
                    success = rv.fvalue->rebin(funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue);
                }
            }
            break;

/************************
 ***    stringarray   ***
 ************************/
        case 99:
            if (rv.type == typeStr) {
                rv.type = typeStrarr;
                rv.arrvalue = CreateStringArray();
                rv.arrvalue->append(*funcargs[0].svalue);
            } else {
                rv.type = typeStrarr;
                rv.arrvalue = CreateStringArray(funcargs[0].lvalue);
            }
            break;

/************************
 ***     nelements    ***
 ************************/
        case 100:
            rv.type = typeCon;
            switch (funcargs[0].type) {
                case typeFits: rv.lvalue = funcargs[0].fvalue->Nelements(); break;
                case typeStr: rv.lvalue = funcargs[0].svalue->length(); break;
                case typeStrarr: rv.lvalue = funcargs[0].arrvalue->count(); break;
                case typeDpArr: rv.lvalue = funcargs[0].dparrvalue->size(); break;
                case typeCom:
                case typeCon:
                case typeDbl:
                    rv.lvalue = 1;
                break;
                case typeUnknown:
                    rv.lvalue = 0;
                break;
                default:
                    rv.lvalue = 0;
                break;
            }
            break;

/************************
 ***     ssastat      ***
 ************************/
        case 101:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 7) success = rv.fvalue->ssastat(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, 0, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
            else success = rv.fvalue->ssastat(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[7].lvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue, funcargs[6].fvalue);
            break;

/************************
 ***      sssa        ***
 ************************/
        case 102: rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 6) success = rv.fvalue->sssa(funcargs[0].ffvalue->c_str(), *funcargs[1].fvalue, 0, funcargs[2].fvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue);
            else success = rv.fvalue->sssa(funcargs[0].ffvalue->c_str(), *funcargs[1].fvalue, funcargs[6].lvalue, funcargs[2].fvalue, funcargs[3].fvalue, funcargs[4].fvalue, funcargs[5].fvalue);
            break;

/************************
 ***     ssaselect    ***
 ************************/
        case 103: {
            int i;
            float s1, s2;

            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                for (i = 1; i <= rv.fvalue->Naxis(2); i++) {
                    s1 = rv.fvalue->ValueAt(rv.fvalue->F_I(1, i));
                    s2 = rv.fvalue->ValueAt(rv.fvalue->F_I(2, i));
                    if ((sqrt(s1 * s1 + s2 * s2) > funcargs[1].dvalue) ||
                        (rv.fvalue->ValueAt(rv.fvalue->F_I(3, i)) < funcargs[2].dvalue) ||
                        (rv.fvalue->ValueAt(rv.fvalue->F_I(4, i)) < funcargs[3].dvalue) ||
                        (rv.fvalue->ValueAt(rv.fvalue->F_I(5, i)) < funcargs[4].dvalue) ||
                        (rv.fvalue->ValueAt(rv.fvalue->F_I(6, i)) > funcargs[5].dvalue))
                        rv.fvalue->setValue(0.0, 7, i);
                }
            }
            }
            break;

/************************
 ***    maxentropy    ***
 ************************/
        case 104: {
            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 3) rv.fvalue->maxEntropy(*funcargs[1].fvalue, funcargs[2].lvalue);
                else rv.fvalue->maxEntropy(*funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].dvalue);
            }
            }
            break;

/************************
 ***    cubeminimum   ***
 ************************/
        case 105:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->CubeMinimum(*funcargs[0].fvalue);
            break;

/************************
 ***    cubemaximum   ***
 ************************/
        case 106:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->CubeMaximum(*funcargs[0].fvalue);
            break;

/************************
 ***      fwhm        ***
 ************************/
        case 107:
            rv.type = typeDbl;
            if (nargs == 3) rv.dvalue = (double)funcargs[0].fvalue->get_fwhm(funcargs[1].lvalue, funcargs[2].lvalue);
            else rv.dvalue = (double)funcargs[0].fvalue->get_fwhm(funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].lvalue);
            break;

/************************
 ***     setbitpix    ***
 ************************/
        case 108:
            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 4) success = rv.fvalue->setType((FitsBitpix)funcargs[1].lvalue, funcargs[2].dvalue, funcargs[3].dvalue);
                else if (nargs == 3) success = rv.fvalue->setType((FitsBitpix)funcargs[1].lvalue, funcargs[2].dvalue);
                else if (nargs == 2) success = rv.fvalue->setType((FitsBitpix)funcargs[1].lvalue);
            }
            break;


/***********************************************************************************
 ***   bytearray, shortarray, longarray, floatarray, doublearray, complexarray   ***
 ***********************************************************************************/
// cases 109 through 114 share the same code
        case 109:
        case 110:
        case 111:
        case 112:
        case 113:
        case 114: {
            FitsBitpix bitpix;
            int n = id + 1;

            switch (n) {
            case 109: bitpix = I1; break;
            case 110: bitpix = I2; break;
            case 111: bitpix = I4; break;
            case 112: bitpix = R4; break;
            case 113: bitpix = R8; break;
            case 114: bitpix = C16; break;
            default: bitpix = NA; success = FALSE; break;
            }
            if (!success) break;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 1) {
                if (funcargs[0].lvalue < 1) success = FALSE;
                else success = rv.fvalue->create(funcargs[0].lvalue, 1, bitpix);
            } else if (nargs == 2) {
                if ((funcargs[0].lvalue < 1) || (funcargs[1].lvalue < 1)) success = FALSE;
                else success = rv.fvalue->create(funcargs[0].lvalue, funcargs[1].lvalue, bitpix);
            } else if (nargs == 3) {
                if ((funcargs[0].lvalue < 1) || (funcargs[1].lvalue < 1) || (funcargs[2].lvalue < 1)) success = FALSE;
                else success = rv.fvalue->create(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].lvalue, bitpix);
            } else success = FALSE;
            }
            break;

/************************
 ***     shrink       ***
 ************************/
        case 115:
            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) {
                if (nargs == 2) {
                    rv.fvalue->shrink(funcargs[1].lvalue);
                } else {
                    rv.fvalue->shrink(funcargs[1].lvalue, funcargs[2].lvalue);
                }
            }
            break;

/************************
 ***    getfitskey    ***
 ************************/
        case 116: {
            char retstr[80];
            int retint;
            double retdouble;
            int extension = 0;
            Fits *fvalue;

            retstr[0] = '\0';
            rv.type = typeStr;
            rv.svalue = CreateString("");
            if (nargs == 3) extension = funcargs[2].lvalue;
            if (funcargs[0].type == typeFits) {
                funcargs[0].fvalue->updateHeader();
                fvalue = funcargs[0].fvalue;
            } else {
                fvalue = CreateFits();
                success = fvalue->OpenFITS(funcargs[0].ffvalue->c_str());
                if (success) {
                    if (extension < 1) {
                        success = (fvalue->hdr = fvalue->ReadFitsHeader() >= 0);
                    } else {
                        success = (fvalue->hdr = fvalue->ReadFitsExtensionHeader(extension) >= 0);
                    }
                    fvalue->CloseFITS();
                }
            }
            success = FALSE;
            if (fvalue->GetStringKey(funcargs[1].svalue->c_str(), retstr)) {
                rv.svalue = CreateString(retstr);
                success = TRUE;
            }
            if (function_options != 1) {
                if (fvalue->GetIntKey(funcargs[1].svalue->c_str(), &retint)) {
                    if (fvalue->GetFloatKey(funcargs[1].svalue->c_str(), &retdouble)) {
                        if (retdouble == (double)retint) {
                            rv.type = typeCon;
                            rv.lvalue = (long)retint;
                        } else {
                            rv.type = typeDbl;
                            rv.dvalue = retdouble;
                        }
                    }
                    success = TRUE;
                }
            }
            if (success == FALSE) {
                dp_output("%s: No such Fits key\n", funcargs[1].svalue->c_str());
                success = TRUE;
            }
            }
            break;

/************************
 ***     polyfit      ***
 ************************/
        case 117: {
            Fits x, err;
            double chisq = 0.0;
            int i;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            x.create(funcargs[0].fvalue->Nelements(), 1, I4);
            err.create(funcargs[0].fvalue->Nelements(), 1, I1);
            for (i = 0; i < funcargs[0].fvalue->Nelements(); i++) {
                x.i4data[i] = i+1;
                err.i1data[i] = 1;
            }
            chisq = polyfit1d(*rv.fvalue, x, *funcargs[0].fvalue, err, funcargs[1].lvalue);
            if (nargs == 3) {
                dpuser_vars[*funcargs[2].svalue] = chisq;
//                variables[funcargs[2].lvalue].type = typeDbl;
//                variables[funcargs[2].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***     sprintf      ***
 ************************/
        case 118:
            rv.type = typeStr;

            rv.svalue = CreateString();
            if (funcargs[1].type == typeCon) rv.svalue->sprintf(funcargs[0].svalue->c_str(), funcargs[1].lvalue);
            else rv.svalue->sprintf(funcargs[0].svalue->c_str(), funcargs[1].dvalue);
            break;

/************************
 ***    photometry    ***
 ************************/
        case 119: {
            double refsum, meassum, scale, epsilon = 2.8;

            rv.type = typeFits;
            rv.fvalue = CreateFits();

            // if (funcargs[2].fvalue->Naxis(1) != 1) {
            // printf("photometry: Reference list must have NAXIS1 == 1\n");
            // success = FALSE;
            // break;
            // }

            switch (function_options) {
                case 1: epsilon = 3.274; break;
                case 2: epsilon = 3.647; break;
                case 4: epsilon = 3.581; break;
                case 8: epsilon = 3.479; break;
                case 16: epsilon = 3.386; break;
                case 32: epsilon = 3.248; break;
                case 64: epsilon = 3.08; break;
                case 128: epsilon = 2.8; break;
                case 256: epsilon = 2.49; break;
                case 512: epsilon = 2.26; break;
                case 1024: epsilon = 1.63; break;
                default: epsilon = 2.8; break;
            }
            funcargs[0].fvalue->multiple_phot(*funcargs[1].fvalue, funcargs[4].lvalue, rv.fvalue, 1, funcargs[3].lvalue);
            rv.fvalue->resize(3, -1);
            meassum = refsum = 0.0;
            for (int i = 0; i < funcargs[2].fvalue->Naxis(2); i++) {
                if (funcargs[2].fvalue->ValueAt(i) < 20.0) {
                    if (rv.fvalue->ValueAt(rv.fvalue->C_I(0, i)) > 0.0) {
                        meassum += rv.fvalue->ValueAt(rv.fvalue->C_I(0, i));
                        refsum += pow(10.0, epsilon - 0.4 * funcargs[2].fvalue->ValueAt(i));
                    }
                }
            }
            scale = refsum / meassum;
            for (int i = 0; i < rv.fvalue->Naxis(2); i++) {
                rv.fvalue->r8data[i * 3 + 1] = rv.fvalue->r8data[i * 3] * scale;
                rv.fvalue->r8data[i * 3 + 2] = (epsilon - log10(rv.fvalue->r8data[i * 3 + 1])) / 0.4;
            }
            }
            break;

/************************
 ***    transcoords   ***
 ************************/
        case 120: {
            double *xref = NULL, *yref = NULL, *xim = NULL, *yim = NULL;
            double SY[10] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double SX[10] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double x, y, xerror, yerror;
            int i, llen, ncoords;

            llen = funcargs[1].fvalue->Naxis(2);
            if (llen < 1) {
                yyerror("Must have at least 3 reference sources");
                success = FALSE;
                break;
            }
            if ((funcargs[1].fvalue->Naxis(1) != 2) || (funcargs[2].fvalue->Naxis(1) != 2)) {
                yyerror("Input matrices are not of correct size: Must be 2xn");
                success = FALSE;
                break;
            }
            if (funcargs[1].fvalue->Naxis(2) != funcargs[2].fvalue->Naxis(2)) {
                yyerror("The two reference lists do not contain the same number of sources");
                success = FALSE;
                break;
            }
            if (funcargs[0].fvalue->Naxis(1) != 2) {
                yyerror("The master coordinate list does not contain 2 coordinates per star");
                success = FALSE;
                break;
            }

            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = rv.fvalue->setType(R8);
            if (success) {
                xref = (double *)malloc(llen * sizeof(double));
                yref = (double *)malloc(llen * sizeof(double));
                xim = (double *)malloc(llen * sizeof(double));
                yim = (double *)malloc(llen * sizeof(double));

                // reference or image stars with values of -1 are rejected (not used for the calculation of the transformation)
                if ((xref == NULL) || (yref == NULL) || (xim == NULL) || (yim == NULL)) {
                    if (xref != NULL) free(xref);
                    if (yref != NULL) free(yref);
                    if (xim != NULL) free(xim);
                    if (yim != NULL) free(yim);
                    success = FALSE;
                    break;
                } else {
                    ncoords = 0;
                    for (i = 0; i < llen; i++) {
                        xref[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(0, i));
                        yref[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(1, i));
                        xim[ncoords] = funcargs[2].fvalue->ValueAt(funcargs[2].fvalue->C_I(0, i));
                        yim[ncoords] = funcargs[2].fvalue->ValueAt(funcargs[2].fvalue->C_I(1, i));
                        if ((xim[ncoords] == -1.) || (yim[ncoords] == -1.) || (xref[ncoords] == -1.) || (yref[ncoords] == -1.)) ncoords--;
                        ncoords++;
                    }
                    success = TRUE;
                }
                if (!(function_options & 8)) {
                    // original code, transformation with polynomial (Thomas)
                    if (success) {
                        if ((function_options & 1) && (ncoords > 2)) {
                            success = trans_matrix(ncoords, 3, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                        } else if ((function_options & 2) && (ncoords > 10)) {
                            success = trans_matrix(ncoords, 10, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                        } else {
                            int nused = 6;
                            if (ncoords < nused) nused = ncoords;
                            success = trans_matrix(ncoords, nused, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                        }
                    }
                    if (success) {
                        if (!(function_options & 4)) {
                            if (function_options & 2)
                                dp_output("transformation matrix is:\nx' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2 + %5gx^2y + %5gxy^2 + %5gx^3 + %5gy^3\ny' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2 + %5gx^2y + %5gxy^2 + %5gx^3 + %5gy^3\n", SX[9], SX[0], SX[1], SX[4], SX[2], SX[3], SX[7], SX[8], SX[5], SX[6], SY[9], SY[0], SY[1], SY[4], SY[2], SY[3], SY[7], SY[8], SY[5], SY[6]);
                            else
                                dp_output("transformation matrix is:\nx' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\ny' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\n", SX[5], SX[0], SX[1], SX[4], SX[2], SX[3], SY[5], SY[0], SY[1], SY[4], SY[2], SY[3]);
                        }
                        for (i = 0; i < rv.fvalue->Naxis(2); i++) {
                            x = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(0, i));
                            y = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(1, i));
                            if (function_options & 2) {
                                rv.fvalue->r8data[rv.fvalue->C_I(0, i)] = SX[0]*x+SX[1]*y+SX[2]*x*x+SX[3]*y*y+SX[4]*x*y+SX[5]*x*x*x+SX[6]*y*y*y+SX[7]*x*x*y+SX[8]*x*y*y+SX[9];
                                rv.fvalue->r8data[rv.fvalue->C_I(1, i)] =  SY[0]*x+SY[1]*y+SY[2]*x*x+SY[3]*y*y+SY[4]*x*y+SY[5]*x*x*x+SY[6]*y*y*y+SY[7]*x*x*y+SY[8]*x*y*y+SY[9];
                            } else {
                                rv.fvalue->r8data[rv.fvalue->C_I(0, i)] = SX[0]*x+SX[1]*y+SX[2]*x*x+SX[3]*y*y+SX[4]*x*y+SX[5];
                                rv.fvalue->r8data[rv.fvalue->C_I(1, i)] =  SY[0]*x+SY[1]*y+SY[2]*x*x+SY[3]*y*y+SY[4]*x*y+SY[5];
                            }
                        }
                    }
                    if (nargs == 5) {
                        dpuser_vars[*funcargs[3].svalue] = xerror;
                        dpuser_vars[*funcargs[4].svalue] = xerror;
//                        variables[funcargs[3].lvalue].type = typeDbl;
//                        variables[funcargs[3].lvalue].dvalue = xerror;
//                        variables[funcargs[4].lvalue].type = typeDbl;
//                        variables[funcargs[4].lvalue].dvalue = yerror;
                    }
                } else { // !(function_options & 8)
                    // option == "rotation", transformation with rotation (Alex)
                    int nrPars = 4; // number of parameters in transformation
                    int nrStars = rv.fvalue->Naxis(2); // number of stars in master list to transform
                    double *trafo = (double *)malloc(nrPars * sizeof(double));
                    // allocate array for covariance matrix
                    double **cov_matrix = (double**)malloc(nrPars * sizeof(int *));
                    for(i = 0; i < nrPars; i++) {
                        cov_matrix[i] = (double*)malloc(nrPars * sizeof(double));
                    }

                    // if xerror- & yerror-variables are provided errors will be calculated
                    if (nargs == 5) {
                        // create vector for xerror
                        dpuser_vars[*funcargs[3].svalue].type = typeFits;
                        dpuser_vars[*funcargs[3].svalue].fvalue = CreateFits();
                        if (!dpuser_vars[*funcargs[3].svalue].fvalue->create(1, nrStars, R8))
                            success = 0;
                        // create vector for yerror
                        dpuser_vars[*funcargs[4].svalue].type = typeFits;
                        dpuser_vars[*funcargs[4].svalue].fvalue = CreateFits();
                        if (!dpuser_vars[*funcargs[4].svalue].fvalue->create(1, nrStars, R8))
                            success = 0;
                    }

                    // Transformation
                    fitrotation(trafo, cov_matrix, ncoords, xref, yref, xim, yim, funcargs[0].fvalue);


                    // calculate return values (apply transformation to masterlist)
                    for(i=0; i < nrStars; i++) {
                        x = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(0, i));
                        y = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(1, i));
                        rv.fvalue->r8data[rv.fvalue->C_I(0, i)] = trafo[0] + x*trafo[2] - y*trafo[3];
                        rv.fvalue->r8data[rv.fvalue->C_I(1, i)] = trafo[1] + x*trafo[3] + y*trafo[2];
                        if (nargs == 5) {
                            // if xerror- & yerror-variables are provided errors are calculated
                            // sig_x' = sqrt(sig_x0^2 + sig_phi^2*x^2 + sig_nju^2*y^2 + 2*sig_x0_phi^2*x - 2*sig_x0_nju^2*y - 2*sig_phi_nju^2*x*y)
                            // sig_y' = sqrt(sig_y0^2 + sig_phi^2*y^2 + sig_nju^2*x^2 + 2*sig_y0_phi^2*y + 2*sig_y0_nju^2*x + 2*sig_phi_nju^2*x*y)
                            // in fact sig_x1 & sig_y' are almost the same: sig_x0==sig_y0, sig_phi==sig_nju, sig_x0_phi==sig_y0_nju, sig_x0_nju^2=-sig_y0_phi^2
                            // so only the last term differs, but since sig_phi_nju are always almost zero it doesnt matter.
                            double same = cov_matrix[2][2] + cov_matrix[0][0]*pow(x,2) + cov_matrix[1][1]*pow(y,2) +
                                    2*cov_matrix[2][0]*x - 2*cov_matrix[2][1]*y;
                            // sig_x'
                            dpuser_vars[*funcargs[3].svalue].fvalue->r8data[dpuser_vars[*funcargs[3].svalue].fvalue->C_I(0, i)] =
                                sqrt(same - 2*cov_matrix[1][0]*x*y);

                            // sig_y'
                            dpuser_vars[*funcargs[4].svalue].fvalue->r8data[dpuser_vars[*funcargs[4].svalue].fvalue->C_I(0, i)] =
                                sqrt(same + 2*cov_matrix[1][0]*x*y);
                        }
                    }
                    free(trafo);
                    free(cov_matrix);
                }
                free(xref);
                free(yref);
                free(xim);
                free(yim);
            }
            }
            break;

/************************
 ***     findfile     ***
 ************************/
        case 121:
            rv.type = typeStrarr;
            rv.arrvalue = CreateStringArray();

            *rv.arrvalue = dpDir::findfile(*funcargs[0].svalue);

            if (rv.arrvalue != NULL) {
                int i = 0, j = 0;
                dpStringList *sorted_list = new dpStringList();

                /* sorted indices for rrv*/
                Fits rrv_sort_arr;
                createStringArrayIndex(rrv_sort_arr, *rv.arrvalue, false);

                dpStringList::iterator iter_old;
                for (i = 0; i < rrv_sort_arr.Nelements(); i++) {

                    iter_old = rv.arrvalue->begin();
                    for(j = 1; j < rrv_sort_arr.i4data[i]; j++) {
                        iter_old++;
                    }
                    /* put values of rrv.arrvalue into new dpStringList in correct order*/
                    (*sorted_list).push_back(*iter_old);
                }

                rv.arrvalue = sorted_list;

            }
            break;

/************************
 ***     markpos      ***
 ************************/
        case 122: {
#ifdef DPQT
            dpUpdateView(*funcargs[0].svalue);
            rv.type = typeFits;

            rv.fvalue = CreateFits();
            markposBuffer = rv.fvalue;

            dpusermutex->lock();
            char args[20];
            if (nargs == 2) snprintf(args, 19, "%i", funcargs[1].lvalue);
            else snprintf(args, 19, "5");
            dpCommandQFitsView("markpos", args, function_options);

            // now wait until the dialog has been closed;
            dpusermutex->lock();
            dpusermutex->unlock();

            if (markposBuffer->Nelements() == 0) {
                rv.type = typeDbl;
                dp_output("markpos: no positions have been marked");
                success = FALSE;
            }
#else
            if (ds9_running() == 0) {
                dp_output("ERROR: No ds9 is running! Please start first ds9 (at least v5.2)\n");
                success = false;
            }
            if (xpa == NULL) {
                if ((xpa = XPAOpen(NULL)) == NULL) {
                    dp_output("Can't open socket to image display server.");
                    success = false;
                }
            }
            if (success) {
                int nx, ny, count, ret, pos, x, y;
                int radius = 0;
                float *data1, *pix;
                double fx, fy;
                dpString tmp, key;
                Fits im, ci;
                size_t lens[NXPA];
                char *bufs[NXPA];
                char *names[NXPA];
                char *messages[NXPA];

                Fits *fvalue = NULL;
                if (funcargs[0].type == typeFits) fvalue = funcargs[0].fvalue;
                else if (funcargs[0].type == typeId) fvalue = dpuser_vars[*(funcargs[0].svalue)].fvalue;

                if (fvalue == NULL) success = false;

                if (success) {
                    if (nargs == 2) radius = funcargs[1].toInt();
                    nx = fvalue->Naxis(1);
                    ny = fvalue->Naxis(2);

                    if ((pix = (float *)malloc(fvalue->Nelements() * sizeof(float))) == NULL)
                        throw dpuserTypeException("ERROR: Failed allocating memory!");
                    data1 = floatdata(*fvalue);
                    if (data1)
                        memcpy(pix, data1, fvalue->Nelements() * sizeof(float));
                    else {
                        free(pix);
                        throw dpuserTypeException("ERROR: Failed copying memory!");
                    }
                    if (data1 && (data1 != fvalue->r4data))
                        free(data1);

                    // display fits
                    dpString accessPoint = "array [xdim=" + dpString::number(nx) +
                                           ",ydim=" + dpString::number(ny) +
                                           ",bitpix=-32]";

                    ret = XPASet(xpa, xpaServer, (char*)accessPoint.c_str(), NULL,
                                 (char*)pix, nx * ny * sizeof(float),
                                 names, messages, NXPA);

                    free(pix);

                    /* error processing */
                    for(int i = 0; i < ret; i++){
                        if(messages[i]) {
                            dp_output("ERROR: %s (%s)\n", messages[i], names[i]);
                        }
                        if(names[i]) {
                            free(names[i]);
                        }
                        if(messages[i]) {
                            free(messages[i]);
                        }
                    }

                    count = 0;
                    rv.type = typeFits;
                    rv.fvalue = CreateFits();
                    if (!rv.fvalue->create(2,100))
                        success = false;
                }

                if (success)
                    if (radius != 0)
                        if (!im.copy(*fvalue))
                            success = false;

                if (success) {
                    dpString sp = dpString(" ");
                    key = "t";
                    try {
                        while ((key != "q") && (xpa != NULL)) {
                            ret = XPAGet(xpa, xpaServer, (char *)"imexam key coordinate image", NULL,
                                         bufs, lens, names, messages, NXPA);

                            if( messages[0] == NULL ){
                                /* extract key and x/y-positions */
                                tmp = bufs[0];
                                tmp = tmp.stripWhiteSpace();
                                pos = tmp.strpos(sp, false);
                                key = tmp.left(pos);
                                tmp.remove(0,pos);
                                tmp = tmp.stripWhiteSpace();
                                x = atoi(tmp.left(tmp.strpos(sp, false)).c_str());
                                y = atoi(tmp.right(tmp.length() - tmp.strpos(sp, false)).c_str());
                                free(bufs[0]);

                                if (key != "q") {
                                    if (radius != 0) {
                                        if (!(function_options & 1)) {
                                            im.max_pixel(&x, &y, radius);
                                        }

                                        ci.circle(im.Naxis(1), im.Naxis(2), x, y, radius);
                                        im.mul(ci);
                                        im.centroid(&fx, &fy);
                                        im.copy(*fvalue);
                                    } else {
                                        fx = (double)x;
                                        fy = (double)y;
                                    }
                                    dp_output("markpos: key %s at (%i, %i)\n", key.c_str(), x, y);

                                    char ckey;
                                    ckey = *(key.c_str());
                                    if ((ckey <= '9') && (ckey >= '1')) {
                                        rv.fvalue->r4data[rv.fvalue->C_I(0, ckey - '1')] = (float)fx;
                                        rv.fvalue->r4data[rv.fvalue->C_I(1, ckey - '1')] = (float)fy;
                                        if (count < ckey - '1')
                                            count = ckey - '1';
                                        else
                                            count--;
                                    } else {
                                        rv.fvalue->r4data[rv.fvalue->C_I(0, count)] = (float)fx;
                                        rv.fvalue->r4data[rv.fvalue->C_I(1, count)] = (float)fy;
                                    }
                                    count++;
                                }
                            }
                            else{
                                /* error processing */
                                dp_output("ERROR: %s (%s)\n", messages[0], names[0]);
                            }
                            if(names[0])
                                free(names[0]);
                            if(messages[0])
                                free(messages[0]);
                        }
                    } catch (dpuserTypeException e) {
                        dp_output("%s", e.reason());
                        success = false;
                    }
                }
                if (success) rv.fvalue->resize(2, count);

            }
#endif /* DPQT */
            }
            break;

/************************
 ***      lmst        ***
 ************************/
        case 123: {
            double mjd0, mjd, gmst, t, ut;

            rv.type = typeDbl;
            mjd = funcargs[0].dvalue - 2400000.5;
            mjd0 = (double)((long)mjd);
            ut = (mjd - mjd0) * 24.0;
            t = (mjd0 - 51544.5) / 36525.0;
            gmst = 6.697374558 + 1.0027379093 * ut + (8640184.812866 + (0.093104 - 6.2e-6 * t) * t) * t / 3600.0;
            if (nargs == 2) rv.dvalue = 24.0 * frac((gmst - funcargs[1].dvalue / 15.0) / 24.0);
            else rv.dvalue = 24.0 * frac(gmst / 24.0);;
            }
            break;

/************************
 ***      wsa         ***
 ************************/
        case 124:
            rv.type = typeFits;

            rv.fvalue = CreateFits();
            if (nargs == 10)
                success = rv.fvalue->wsa(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue, funcargs[5].lvalue, funcargs[6].fvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue);
            else
                success = rv.fvalue->wsa(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue, funcargs[5].lvalue, funcargs[6].fvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue, funcargs[10].fvalue);
            break;

/************************
 ***      swsa        ***
 ************************/
        case 125:
            rv.type = typeFits;

            rv.fvalue = CreateFits();
            if (nargs == 11)
                success = rv.fvalue->wsa(funcargs[0].ffvalue->c_str(), funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].dvalue, funcargs[5].lvalue, funcargs[6].lvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue, funcargs[10].fvalue, NULL, funcargs[1].fvalue);
            else
                success = rv.fvalue->wsa(funcargs[0].ffvalue->c_str(), funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].dvalue, funcargs[5].lvalue, funcargs[6].lvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue, funcargs[10].fvalue, funcargs[11].fvalue, funcargs[1].fvalue);
            break;

/************************
 ***     centroids    ***
 ************************/
        case 126:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = funcargs[0].fvalue->centroids(*rv.fvalue, *funcargs[1].fvalue, funcargs[2].lvalue);
            break;

/************************
 ***     maxima       ***
 ************************/
        case 127:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (!rv.fvalue->copy(*funcargs[1].fvalue)) {
                success = FALSE;
                break;
            }
            switch (function_options) {
                case 0:
                case 1: success = funcargs[0].fvalue->maxima(*rv.fvalue, funcargs[2].lvalue, 0);
                break;
                case 2: success = funcargs[0].fvalue->maxima(*rv.fvalue, funcargs[2].lvalue, 1);
                default: break;
            }
            break;

/************************
 ***    fileexists    ***
 ************************/
        case 128: {
            FILE *fd;

            rv.type = typeCon;
            rv.lvalue = ((fd = fopen(funcargs[0].svalue->c_str(), "rb")) != NULL);
            if (rv.lvalue) fclose(fd);
            }
            break;

/************************
 ***     filesize     ***
 ************************/
        case 129: {
            FILE *fd;

            rv.type = typeCon;
            fd = fopen(funcargs[0].svalue->c_str(), "rb");
            if (fd != NULL) {
                fseek(fd, 0L, SEEK_END);
                rv.lvalue = ftell(fd);
                fclose(fd);
            } else rv.lvalue = -1;
            }
            break;

/************************
 ***      dir         ***
 ************************/
        case 130: {
            dpString filter;
            rv.type = typeStrarr;
            rv.arrvalue = CreateStringArray();

            if (nargs == 1) {
                filter = *funcargs[0].svalue;
             } else {
                filter = "*";
             }

            if (filter == "") {
                filter = "*";
            }

            if (function_options == 1) {
                *rv.arrvalue += dpDir::findfile(filter);
            } else {
                *rv.arrvalue += dpDir::dir(filter);
            }
            }
            break;

/************************
 ***     polyfitxy    ***
 ************************/
        case 131: {
            Fits err;
            double chisq = 0.0;
            int i;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            err.create(funcargs[0].fvalue->Nelements(), 1, I1);
            for (i = 0; i < funcargs[0].fvalue->Nelements(); i++) {
                err.i1data[i] = 1;
            }
            chisq = polyfit1d(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, err, funcargs[2].lvalue);
            if (nargs == 4) {
                dpuser_vars[*funcargs[3].svalue] = chisq;
//                variables[funcargs[3].lvalue].type = typeDbl;
//                variables[funcargs[3].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***      sort        ***
 ************************/
        case 132:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (funcargs[0].type == typeFits)
                rv.fvalue->createFitsIndex(*funcargs[0].fvalue, function_options == 1);
            else if (funcargs[0].type == typeStr)
                createStringIndex(*rv.fvalue, *funcargs[0].svalue, function_options == 1);
            else if (funcargs[0].type == typeStrarr)
                createStringArrayIndex(*rv.fvalue, *funcargs[0].arrvalue, function_options == 1);
            break;

/************************
 ***      char        ***
 ************************/
        case 133:
            char value[2];
            value[1] = 0;
            rv.type = typeStr;
            rv.svalue = CreateString();
            value[0] = (char)funcargs[0].lvalue;
            rv.svalue->append(value);
            break;

/************************
 ***     complex      ***
 ************************/
        case 134:
            if (funcargs[0].type != funcargs[1].type) {
                success = 0;
                yyerror("complex: Arguments must be of same type");
                break;
            }
            if (funcargs[0].type == typeFits) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->rr_ri(*funcargs[0].fvalue, *funcargs[1].fvalue);
            } else {
                rv.type = typeCom;
                rv.cvalue = CreateComplex(funcargs[0].dvalue, funcargs[1].dvalue);
            }
            break;

/************************
 ***     strpos       ***
 ************************/
        case 135:
            if (funcargs[0].type == typeStr) {
                rv.type = typeCon;
//#ifdef NO_QT
                rv.lvalue = funcargs[0].svalue->strpos(*funcargs[1].svalue, function_options != 1);
/*#else
                rv.lvalue = funcargs[0].svalue->find(*funcargs[1].svalue, 0, function_options != 1);
#endif*/
                if (rv.lvalue > -1) rv.lvalue++;
            } else {
                dpint64 i;
                long l;

                rv.type = typeFits;
                rv.fvalue = CreateFits();
                success = rv.fvalue->create(funcargs[0].arrvalue->count(), 1, I4);
                if (!success) break;
                for (i = 0; i < funcargs[0].arrvalue->count(); i++) {
//#ifdef NO_QT
                    l = (*funcargs[0].arrvalue)[i].strpos(*funcargs[1].svalue, function_options != 1);
/*#else
                    l = (*funcargs[0].arrvalue)[i].find(*funcargs[1].svalue, 0, function_options != 1);
#endif*/
                    if (l > -1) l++;
                    rv.fvalue->i4data[i] = l;
                }
            }
            break;

/************************
 ***     clean        ***
 ************************/
        case 136:
            rv.type = typeFits;
            rv.clone(funcargs[0]);
            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue].type = typeFits;
                dpuser_vars[*funcargs[4].svalue].fvalue = CreateFits();
                rv.fvalue->clean(*funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].dvalue, dpuser_vars[*funcargs[4].svalue].fvalue);
            } else {
                rv.fvalue->clean(*funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].dvalue);
            }
            break;

/************************
 ***     collapse     ***
 ************************/
        case 137:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->collapse(*funcargs[0].fvalue, funcargs[1].lvalue);
            break;

/************************
 ***     magnify      ***
 ************************/
        case 138:
            rv.clone(funcargs[0]);
            rv.fvalue->enlarge(funcargs[1].lvalue, 2);
            if (nargs == 3) rv.fvalue->smooth(funcargs[2].dvalue);
            break;

/************************
 ***     wsastat      ***
 ************************/
        case 139:
            rv.type = typeFits;

            rv.fvalue = CreateFits();
            if (nargs == 10)
                success = rv.fvalue->wsastat(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue, funcargs[5].lvalue, funcargs[6].fvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue);
            else
                success = rv.fvalue->wsastat(funcargs[0].ffvalue->c_str(), funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue, funcargs[5].lvalue, funcargs[6].fvalue, funcargs[7].fvalue, funcargs[8].fvalue, funcargs[9].fvalue, funcargs[10].fvalue);
            break;

/************************
 ***     gaussfit     ***
 ************************/
        case 140: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[3].fvalue);
            chisq = gaussfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***    gauss2dfit    ***
 ************************/
        case 141: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[2].fvalue);
            chisq = gauss2dfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue);

            if (nargs == 4) {
                dpuser_vars[*funcargs[3].svalue] = chisq;
//                variables[funcargs[3].lvalue].type = typeDbl;
//                variables[funcargs[3].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***   polyfitxyerr   ***
 ************************/
        case 142: {
            Fits err;
            double chisq = 0.0;
            int i;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            err.create(funcargs[0].fvalue->Nelements(), 1, R8);
            if (funcargs[3].type == typeFits) {
                for (i = 0; i < funcargs[3].fvalue->Nelements(); i++) {
                    err.r8data[i] = funcargs[3].fvalue->ValueAt(i);
                }
            } else {
                for (i = 0; i < funcargs[3].fvalue->Nelements(); i++) {
                    err.r8data[i] = funcargs[3].dvalue;
                }
            }
            chisq = polyfit1d(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, err, funcargs[2].lvalue);
            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***       psf        ***
 ************************/
        case 143: {
            Fits *cube;
            int i, xc, yc;

            cube = CreateFits();
            if (!cube->create(funcargs[0].fvalue->Naxis(1), funcargs[0].fvalue->Naxis(2), funcargs[1].fvalue->Naxis(2))) break;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            xc = funcargs[0].fvalue->Naxis(1) / 2 + 1;
            yc = funcargs[0].fvalue->Naxis(2) / 2 + 1;

            for (i = 1; i <= funcargs[1].fvalue->Naxis(2); i++) {
                rv.fvalue->copy(*funcargs[0].fvalue);
                rv.fvalue->shift((int)(xc - (*funcargs[1].fvalue)(1, i)), (int)(yc - (*funcargs[1].fvalue)(2, i)), 2);
                rv.fvalue->div((*rv.fvalue)(xc, yc));
                cube->setRange(*rv.fvalue, -1, -1, -1, -1, i, i);
            }
            switch (function_options) {
                case 2: cube_avg(*cube, *rv.fvalue); break;
                case 4: rv.fvalue->CubeMinimum(*cube); break;
                case 8: rv.fvalue->CubeMaximum(*cube); break;
                default: rv.fvalue->CubeMedian(*cube); break;
            }
            }
            break;

/************************
 ***       pwd        ***
 ************************/
        case 144:
            rv.type = typeStr;
            rv.svalue = CreateString(dpDir::currentDirPath());
            break;

/************************
 ***    quickgauss    ***
 ************************/
        case 145:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->qgauss(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].lvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 ***      getenv      ***
 ************************/
        case 146: {
            char *var;

            var = getenv(funcargs[0].svalue->c_str());
            rv.type = typeStr;
            if (var == NULL) rv.svalue = CreateString("");
            else rv.svalue = CreateString(var);
            }
            break;

/************************
 ***      cblank      ***
 ************************/
        case 147:
            rv.type = typeFits;
            rv.clone(funcargs[0]);
            if (nargs == 1) rv.fvalue->cblank();
            else rv.fvalue->cblank(funcargs[1].dvalue);
            break;

/************************
 ***       now        ***
 ************************/
        case 148: {
            if (nargs == 1) {
                time_t start_time;
                time(&start_time);
                rv.lvalue = start_time;
            } else {
                CJulianDay jd;
                time_t t_time;
                struct tm *n_time;

                rv.type = typeDbl;
                time(&t_time);
                n_time = gmtime(&t_time);
                jd.SetJD(n_time->tm_mday, n_time->tm_mon + 1, n_time->tm_year + 1900, n_time->tm_hour, n_time->tm_min, n_time->tm_sec);
                rv.dvalue = (double)jd;
            }
            }
            break;

#ifdef HAS_PGPLOT
/************************
 ***      pgband      ***
 ************************/
        case 149: {
            float x, y;
            char ch[2];

            rv.type = typeCon;
            ch[1] = (char)0;
            x = dpuser_vars[*funcargs[4].svalue].toDouble();
//            if (variables[funcargs[4].lvalue].type == typeCon) x = (float)variables[funcargs[4].lvalue].lvalue;
//            else x = (float)variables[funcargs[4].lvalue].dvalue;
            y = dpuser_vars[*funcargs[4].svalue].toDouble();
//            if (variables[funcargs[5].lvalue].type == typeCon) y = (float)variables[funcargs[5].lvalue].lvalue;
//            else y = (float)variables[funcargs[5].lvalue].dvalue;
            rv.lvalue = cpgband(funcargs[0].lvalue, funcargs[1].lvalue, funcargs[2].dvalue, funcargs[3].dvalue, &x, &y, ch);
            dpuser_vars[*funcargs[4].svalue].type = typeDbl;
            dpuser_vars[*funcargs[4].svalue].dvalue = x;
            dpuser_vars[*funcargs[5].svalue].type = typeDbl;
            dpuser_vars[*funcargs[5].svalue].dvalue = y;
            dpuser_vars[*funcargs[6].svalue].type = typeStr;
            dpuser_vars[*funcargs[6].svalue].svalue = CreateString(ch);
            }
            break;

/************************
 *** pgbeg (pgbegin)  ***
 ************************/
        case 150:
        case 151:
            rv.type = typeCon;
            rv.lvalue = cpgbeg(funcargs[0].lvalue, funcargs[1].svalue->c_str(), funcargs[2].lvalue, funcargs[3].lvalue);
            break;

/************************
 *** pgcurs (pgcurse) ***
 ************************/
        case 152:
        case 153: {
            float x, y;
            char ch[2];

            rv.type = typeCon;
            ch[1] = (char)0;
            x = dpuser_vars[*funcargs[0].svalue].toDouble();
//            if (variables[funcargs[0].lvalue].type == typeCon) x = (float)variables[funcargs[0].lvalue].lvalue;
//            else x = (float)variables[funcargs[0].lvalue].dvalue;
            y = dpuser_vars[*funcargs[1].svalue].toDouble();
//            if (variables[funcargs[1].lvalue].type == typeCon) y = (float)variables[funcargs[1].lvalue].lvalue;
//            else y = (float)variables[funcargs[1].lvalue].dvalue;
            rv.lvalue = cpgcurs(&x, &y, ch);
            dpuser_vars[*funcargs[0].svalue].type = typeDbl;
            dpuser_vars[*funcargs[0].svalue].dvalue = x;
            dpuser_vars[*funcargs[1].svalue].type = typeDbl;
            dpuser_vars[*funcargs[1].svalue].dvalue = y;
            dpuser_vars[*funcargs[2].svalue].type = typeStr;
            dpuser_vars[*funcargs[2].svalue].svalue = CreateString(ch);
            }
            break;

/************************
 ***      pgopen      ***
 ************************/
        case 154:
            rv.type = typeCon;
            rv.lvalue = cpgopen(funcargs[0].svalue->c_str());
            break;

/************************
 ***      pgrnd       ***
 ************************/
        case 155: {
            int nsub;
            rv.type = typeDbl;
            rv.dvalue = cpgrnd(funcargs[0].dvalue, &nsub);
            dpuser_vars[*funcargs[1].svalue].type = typeCon;
            dpuser_vars[*funcargs[1].svalue].lvalue = nsub;
            }
            break;

#endif /* HAS_PGPLOT */

/************************
 ***      polar       ***
 ************************/
        case 156:
            if (funcargs[0].type != funcargs[1].type) {
                success = 0;
                yyerror("polar: Arguments must be of same type");
                break;
            }
            if (funcargs[0].type == typeFits) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->rr_aa(*funcargs[0].fvalue, *funcargs[1].fvalue);
            } else {
                rv.type = typeCom;
                rv.cvalue = CreateComplex(complex_polar(funcargs[0].dvalue, funcargs[1].dvalue));
            }
            break;

/************************
 ***    transmatrix   ***
 ************************/
        case 157: {
            double *xref = NULL, *yref = NULL, *xim = NULL, *yim = NULL;
//          double SY[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
//          double SX[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double SY[10] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double SX[10] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double xerror, yerror;
            int i, llen, ncoords;

            llen = funcargs[0].fvalue->Naxis(2);
            if (llen < 1) {
                yyerror("Must have at least 3 reference sources");
                success = FALSE;
                break;
            }
            if ((funcargs[0].fvalue->Naxis(1) != 2) || (funcargs[1].fvalue->Naxis(1) != 2)) {
                yyerror("Input matrices are not of correct size: Must be 2xn");
                success = FALSE;
                break;
            }
            if (funcargs[0].fvalue->Naxis(2) != funcargs[1].fvalue->Naxis(2)) {
                yyerror("The two reference lists do not contain the same number of sources");
                success = FALSE;
                break;
            }

            rv.type = typeFits;
            rv.fvalue = CreateFits();

            xref = (double *)malloc(llen * sizeof(double));
            yref = (double *)malloc(llen * sizeof(double));
            xim = (double *)malloc(llen * sizeof(double));
            yim = (double *)malloc(llen * sizeof(double));

            if ((xref == NULL) || (yref == NULL) || (xim == NULL) || (yim == NULL)) {
                if (xref != NULL) free(xref);
                if (yref != NULL) free(yref);
                if (xim != NULL) free(xim);
                if (yim != NULL) free(yim);
                success = FALSE;
                break;
            } else {
                ncoords = 0;
                for (i = 0; i < llen; i++) {
                    xref[ncoords] = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(0, i));
                    yref[ncoords] = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(1, i));
                    xim[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(0, i));
                    yim[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(1, i));
                    if ((xim[ncoords] == -1.) || (yim[ncoords] == -1.) || (xref[ncoords] == -1.) || (yref[ncoords] == -1.)) ncoords--;
                    ncoords++;
                }
                success = TRUE;
            }

            if (success) {
                if (function_options & 16) { // Kabsch algorithm
                    gsl_matrix *X, *Y, *U;
                    gsl_vector *t;
                    X = gsl_matrix_alloc(ncoords, 2);
                    Y = gsl_matrix_alloc(ncoords, 2);
                    U = gsl_matrix_alloc(2, 2);
                    t = gsl_vector_alloc(2);
                    for (i = 0; i < ncoords; i++) {
                        gsl_matrix_set(X, i, 0, xref[i]);
                        gsl_matrix_set(X, i, 1, yref[i]);
                        gsl_matrix_set(Y, i, 0, xim[i]);
                        gsl_matrix_set(Y, i, 1, yim[i]);
                    }
                    success = kabsch2d(ncoords, X, Y, U, t, NULL);
                    rv.fvalue->create(1, 3, R8);
                    rv.fvalue->r8data[0] = gsl_vector_get(t, 0);
                    rv.fvalue->r8data[1] = gsl_vector_get(t, 1);
                    rv.fvalue->r8data[2] = asin(gsl_matrix_get(U, 1, 0));
                    if (!(function_options & 8)) {
                        dp_output("transformation is:\nx0 = %g, y0 = %g, a  = %g\n", rv.fvalue->r8data[0], rv.fvalue->r8data[1], rv.fvalue->r8data[2]);
                    }
                    gsl_matrix_free(X);
                    gsl_matrix_free(Y);
                    gsl_matrix_free(U);
                    gsl_vector_free(t);
                } else if (!(function_options & 2)) {
                    // original code, transformation with polynomial (Thomas)
                    if ((function_options == 1) && (ncoords > 2)) {
                       success = trans_matrix(ncoords, 3, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                    } else if ((function_options & 4) && (ncoords > 10)) {
                       success = trans_matrix(ncoords, 10, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                    } else {
                       success = trans_matrix(ncoords, ncoords, xref, yref, xim, yim, SX, SY, &xerror, &yerror);
                    }

                    if (success) {
                        if (function_options & 4) {
                            if (!(function_options & 8)) {
                                dp_output("transformation matrix is:\nx' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2 + %5gx^2y + %5gxy^2 + %5gx^3 + %5gy^3\ny' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2 + %5gx^2y + %5gxy^2 + %5gx^3 + %5gy^3\n", SX[9], SX[0], SX[1], SX[4], SX[2], SX[3], SX[7], SX[8], SX[5], SX[6], SY[9], SY[0], SY[1], SY[4], SY[2], SY[3], SY[7], SY[8], SY[5], SY[6]);
                            }

                            success = rv.fvalue->create(2, 10, R8);
                            rv.fvalue->r8data[0] = SX[9];
                            rv.fvalue->r8data[1] = SX[0];
                            rv.fvalue->r8data[2] = SX[1];
                            rv.fvalue->r8data[3] = SX[4];
                            rv.fvalue->r8data[4] = SX[2];
                            rv.fvalue->r8data[5] = SX[3];
                            rv.fvalue->r8data[6] = SX[7];
                            rv.fvalue->r8data[7] = SX[8];
                            rv.fvalue->r8data[8] = SX[5];
                            rv.fvalue->r8data[9] = SX[6];
                            rv.fvalue->r8data[10] = SY[9];
                            rv.fvalue->r8data[11] = SY[0];
                            rv.fvalue->r8data[12] = SY[1];
                            rv.fvalue->r8data[13] = SY[4];
                            rv.fvalue->r8data[14] = SY[2];
                            rv.fvalue->r8data[15] = SY[3];
                            rv.fvalue->r8data[16] = SY[7];
                            rv.fvalue->r8data[17] = SY[8];
                            rv.fvalue->r8data[18] = SY[5];
                            rv.fvalue->r8data[19] = SY[6];

                        } else {
                            if (!(function_options & 8)) {
                                dp_output("transformation matrix is:\nx' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\ny' = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\n", SX[5], SX[0], SX[1], SX[4], SX[2], SX[3], SY[5], SY[0], SY[1], SY[4], SY[2], SY[3]);
                            }

                            success = rv.fvalue->create(2, 6, R8);
                            rv.fvalue->r8data[0] = SX[5];
                            rv.fvalue->r8data[1] = SX[0];
                            rv.fvalue->r8data[2] = SX[1];
                            rv.fvalue->r8data[3] = SX[4];
                            rv.fvalue->r8data[4] = SX[2];
                            rv.fvalue->r8data[5] = SX[3];
                            rv.fvalue->r8data[6] = SY[5];
                            rv.fvalue->r8data[7] = SY[0];
                            rv.fvalue->r8data[8] = SY[1];
                            rv.fvalue->r8data[9] = SY[4];
                            rv.fvalue->r8data[10] = SY[2];
                            rv.fvalue->r8data[11] = SY[3];
                        }
                        if (nargs == 5) {
                            dpuser_vars[*funcargs[2].svalue] = xerror;
                            dpuser_vars[*funcargs[3].svalue] = xerror;
//                            variables[funcargs[2].lvalue].type = typeDbl;
//                            variables[funcargs[2].lvalue].dvalue = xerror;
//                            variables[funcargs[3].lvalue].type = typeDbl;
//                            variables[funcargs[3].lvalue].dvalue = yerror;
                        }
                    }
                } else { // !(function_options & 2)
                    success = rv.fvalue->create(1, 4, R8);
                    if (success) {
                        // option == "rotation", transformation with rotation (Alex)
                        int nrPars = 4; // number of parameters in transformation
                        double *trafo = (double *)malloc(nrPars * sizeof(double));
                        // allocate array for covariance matrix
                        double **cov_matrix = (double**)malloc(nrPars * sizeof(int *));
                        for(i = 0; i < nrPars; i++) {
                            cov_matrix[i] = (double*)malloc(nrPars * sizeof(double));
                        }

                        // Transformation
                        fitrotation(trafo, cov_matrix, ncoords, xref, yref, xim, yim, NULL);

                        dp_output("transformation is:\nx0 = %g, y0 = %g, f  = %g, a  = %g\n", trafo[0], trafo[1], trafo[2], trafo[3]);
                        rv.fvalue->r8data[0] = trafo[0];
                        rv.fvalue->r8data[1] = trafo[1];
                        rv.fvalue->r8data[2] = trafo[2];
                        rv.fvalue->r8data[3] = trafo[3];

                        // if xerror- & yerror-variables are provided errors will be calculated
                        if (nargs > 3) {
                            // create vector for errors (sigma_x0, sigma_y0, sigma_f, )
                            dpuser_vars[*funcargs[2].svalue].type = typeFits;
                            dpuser_vars[*funcargs[2].svalue].fvalue = CreateFits();
                            if (!dpuser_vars[*funcargs[2].svalue].fvalue->create(1, nrPars, R8))
                                success = 0;

                            float phi = trafo[2]*cos(trafo[3]);
                            float nju = trafo[2]*sin(trafo[3]);

                            float nenner = nju*nju+phi*phi;
                            float dfdphi = phi/(sqrt(nenner));
                            float dfdnju = nju/(sqrt(nenner));
                            float dadnju = phi/nenner;
                            float dadphi = -nju/nenner;

                            dpuser_vars[*funcargs[2].svalue].fvalue->r8data[dpuser_vars[*funcargs[2].svalue].fvalue->C_I(0, 0)] = sqrt(cov_matrix[2][2]); // sigma_x0
                            dpuser_vars[*funcargs[2].svalue].fvalue->r8data[dpuser_vars[*funcargs[2].svalue].fvalue->C_I(0, 1)] = sqrt(cov_matrix[3][3]); // sigma_y0
                            float sigma_f = sqrt(pow(dfdnju*cov_matrix[1][1], 2) + pow(dfdphi*cov_matrix[0][0], 2) + 2*dfdnju*dfdphi*cov_matrix[1][0]);
                            dpuser_vars[*funcargs[2].svalue].fvalue->r8data[dpuser_vars[*funcargs[2].svalue].fvalue->C_I(0, 2)] = sigma_f; // sigma_f
                            float sigma_a = sqrt(pow(dadnju*cov_matrix[1][1], 2) + pow(dadphi*cov_matrix[0][0], 2) + 2*dadnju*dadphi*cov_matrix[1][0]);
                            dpuser_vars[*funcargs[2].svalue].fvalue->r8data[dpuser_vars[*funcargs[2].svalue].fvalue->C_I(0, 3)] = sigma_a; // sigma_a
                        }

                        if (nargs == 5) {
                            dpuser_vars[*funcargs[3].svalue] = 0.0;
//                            variables[funcargs[3].lvalue].type = typeDbl;
//                            variables[funcargs[3].lvalue].dvalue = 0.0;
                        }
                    }
                }
            }
            free(xref);
            free(yref);
            free(xim);
            free(yim);
            }
            break;

/************************
 ***     transform    ***
 ************************/
        case 158: {
            double x, y, SX[6], SY[6];
            int i;

            if ((funcargs[1].fvalue->Naxis(1) != 2) || (funcargs[1].fvalue->Naxis(2) != 6)) {
                yyerror("Transformation matrix must be 2x6");
                success = FALSE;
                break;
            }
            if (funcargs[0].fvalue->Naxis(1) != 2) {
                yyerror("The master coordinate list does not contain 2 coordinates per star");
                success = FALSE;
                break;
            }

            rv.type = typeFits;
            if (isVariable(funcargs[0].fvalue) == 1) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->copy(*funcargs[0].fvalue);
            } else
                rv.fvalue = funcargs[0].fvalue;
            if (success) success = rv.fvalue->setType(R8);
            if (success) {
                SX[5] = funcargs[1].fvalue->r8data[0];
                SX[0] = funcargs[1].fvalue->r8data[1];
                SX[1] = funcargs[1].fvalue->r8data[2];
                SX[4] = funcargs[1].fvalue->r8data[3];
                SX[2] = funcargs[1].fvalue->r8data[4];
                SX[3] = funcargs[1].fvalue->r8data[5];
                SY[5] = funcargs[1].fvalue->r8data[6];
                SY[0] = funcargs[1].fvalue->r8data[7];
                SY[1] = funcargs[1].fvalue->r8data[8];
                SY[4] = funcargs[1].fvalue->r8data[9];
                SY[2] = funcargs[1].fvalue->r8data[10];
                SY[3] = funcargs[1].fvalue->r8data[11];
                for (i = 0; i < rv.fvalue->Naxis(2); i++) {
                    x = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(0, i));
                    y = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(1, i));
                    rv.fvalue->r8data[rv.fvalue->C_I(0, i)] = SX[0]*x+SX[1]*y+SX[2]*x*x+SX[3]*y*y+SX[4]*x*y+SX[5];
                    rv.fvalue->r8data[rv.fvalue->C_I(1, i)] =  SY[0]*x+SY[1]*y+SY[2]*x*x+SY[3]*y*y+SY[4]*x*y+SY[5];
                }
            }
            }
            break;

/************************
 ***     invert       ***
 ************************/
        case 159:
            rv.type = typeFits;
            rv.clone(funcargs[0]);
            if (success) success = rv.fvalue->ginvert();
            break;

/************************
 ***     transpose    ***
 ************************/
        case 160:
            rv.type = typeFits;
            rv.clone(funcargs[0]);
            if (success) success = rv.fvalue->rot90(90);
            if (success) success = rv.fvalue->flip(1);
            break;

/************************
 ***    isvariable    ***
 ************************/
        case 161:
            rv.type = typeCon;
            rv.lvalue = dpuser_vars.count(*funcargs[0].svalue);
            break;

/************************
 ***        pi        ***
 ************************/
        case 162:
            rv.type = typeDbl;
            rv.dvalue = 2.0 * acos(0.0);

            break;

/************************
 ***    convolve      ***
 ************************/
        case 163:
            rv.type  = typeFits;
            rv.clone(funcargs[0]);
            if (success) success = rv.fvalue->convolve(*funcargs[1].fvalue);
            break;

/************************
 ***      gammp       ***
 ************************/
        case 164:
            rv.type  = typeDbl;
//          rv.dvalue = gammp(funcargs[0].dvalue, funcargs[1].dvalue);
            rv.dvalue = gsl_sf_gamma_inc_P(funcargs[0].dvalue, funcargs[1].dvalue);
            break;

/************************
 ***      reform      ***
 ************************/
        case 165:
            if (funcargs[0].type != typeFits) {
                rv.clone(funcargs[0]);
                break;
            }
            if (nargs == 1) {
                rv.type = typeFits;
                rv.clone(funcargs[0]);
                if (success) rv.fvalue->deflate();
            } else {
                long n = funcargs[1].lvalue;

                if (nargs > 2) n *= funcargs[2].lvalue;
                if (nargs > 3) n *= funcargs[3].lvalue;
                if (n != (long)funcargs[0].fvalue->Nelements()) {
                    dp_output("reform: must have the same number of elements as the original array\n");
                    success = FALSE;
                } else {
                    rv.type = typeFits;
                    rv.clone(funcargs[0]);
                    if (success) {
                        if (nargs > 3) rv.fvalue->extensionType = IMAGE;
                        rv.fvalue->setNaxis(0, nargs - 1);
                        for (n = 1; n < nargs; n++) {
                            rv.fvalue->setNaxis(n, funcargs[n].lvalue);
                        }
                        for (n = nargs; n < 9; n++) {
                            rv.fvalue->setNaxis(n, 1);
                        }
                    }
                }
            }
            break;

/************************
 ***       find       ***
 ************************/
        case 166: {
            Fits *roundlim, *sharplim;
            if (nargs == 3) {
                roundlim = CreateFits();
                roundlim->create(2, 1);
                roundlim->r4data[0] = -1.0 ; roundlim->r4data[1] = 1.0;
                sharplim = CreateFits();
                sharplim->create(2, 1);
                sharplim->r4data[0] = 0.2 ; sharplim->r4data[1] = 1.0;
            } else if (nargs == 4) {
                roundlim = funcargs[3].fvalue;
                sharplim = CreateFits();
                sharplim->create(2, 1);
                sharplim->r4data[0] = 0.2 ; sharplim->r4data[1] = 1.0;
            } else {
                roundlim = funcargs[3].fvalue;
                sharplim = funcargs[4].fvalue;
            }
            rv.type  = typeFits;
            rv.fvalue = CreateFits();
            success = find(*funcargs[0].fvalue, *rv.fvalue, funcargs[1].dvalue, funcargs[2].dvalue, *roundlim, *sharplim, function_options == 0);
            success = true;
						}
            break;

/************************
 ***    histogram     ***
 ************************/
        case 167: {
            double min, max, binsize;

            rv.fvalue = CreateFits();
            if (nargs == 4) {
                min = funcargs[1].dvalue;
                max = funcargs[2].dvalue;
                binsize = funcargs[3].dvalue;
            } else if (nargs == 3) {
                min = funcargs[1].dvalue;
                max = funcargs[2].dvalue;
                binsize = 1.0;
            } else if (nargs == 2) {
                min = funcargs[1].dvalue;
                max = funcargs[0].fvalue->get_max();
                binsize = 1.0;
            } else {
                funcargs[0].fvalue->get_minmax(&min, &max);
                binsize = 1.0;
            }
            if (function_options == 0)
                success = rv.fvalue->histogram(*funcargs[0].fvalue, min, max, binsize);
            else if (function_options == 1)
                success = rv.fvalue->histogram_indices(*funcargs[0].fvalue, min, max, binsize);
            }
            break;

/************************
 ***     meandev      ***
 ************************/
        case 168:
            rv.type = typeDbl;
            if (nargs == 1) rv.dvalue = funcargs[0].fvalue->get_meandev();
            else rv.dvalue = funcargs[0].fvalue->get_meandev(funcargs[1].dvalue);
            break;

/************************
 ***     version      ***
 ************************/
        case 169: {
            dpString tmp(DPUSERVERSION);
            tmp += DP_VERSION;

            rv.type = typeStr;
            rv.svalue = CreateString(tmp);
            }
            break;

/************************
 ***    spifficube    ***
 ************************/
        case 170: {
            int mode = 0;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (function_options == 1) mode = 1;
            if (function_options == 2) mode = 2;

            success = spifficube(*funcargs[0].fvalue, *rv.fvalue, mode);
            }
            break;

/************************
 ***  spiffiuncube    ***
 ************************/
        case 171: {
            int mode = 0;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (function_options == 1) mode = 1;
            if (function_options == 2) mode = 2;

            success = spiffiuncube(*funcargs[0].fvalue, *rv.fvalue, mode);
            }
            break;

/************************
 ***   spiffishift    ***
 ************************/
        case 172: {
            int mode = 0;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (function_options == 1) mode = 1;
            if (function_options == 2) mode = 2;

            success = spiffishift(*funcargs[0].fvalue, *rv.fvalue, mode);
            }
            break;

/************************
 ***      bezier      ***
 ************************/
        case 173:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 1) {
                funcargs[0].fvalue->BezierInterpolate(*rv.fvalue, 1);
            } else {
                funcargs[0].fvalue->BezierInterpolate(*rv.fvalue, funcargs[1].lvalue);
            }
            break;

/************************
 ***     bezier1d     ***
 ************************/
        case 174: {
            Dim dim;
            Fits actioncube;

            dim.x = funcargs[0].fvalue->Naxis(1);
            dim.y = dim.z = 1;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[0].fvalue);
            rv.fvalue->setType(R4);
            actioncube.copy(*funcargs[1].fvalue);
            actioncube.setType(I2);
            interpol1d(rv.fvalue->r4data, actioncube.i2data, dim, 100);
            }
            break;

/************************
 ***      moffat      ***
 ************************/
        case 175:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 4) success = rv.fvalue->moffat(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            else if (nargs == 5) success = rv.fvalue->moffat(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue, funcargs[4].dvalue);
            else success = rv.fvalue->moffat(dpuser_vars["naxis1"].lvalue, dpuser_vars["naxis2"].lvalue, funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue, funcargs[4].dvalue, funcargs[5].dvalue);
            dpuser_vars["naxis1"].lvalue = onaxis1;
            dpuser_vars["naxis2"].lvalue = onaxis2;
            break;

/************************
 *** readfitsextension***
 ************************/
        case 176: {
            int extension = 0;
            int i, j;
            int x[6] = { 0, 0, 0, 0, 0, 0 };

            if (funcargs[1].type == typeStr) {
                Fits _tmp;
                extension = _tmp.FindExtensionByName(funcargs[0].svalue->c_str(), funcargs[1].svalue->c_str());
            } else {
                extension = funcargs[1].lvalue;
            }
            if (extension <= 0) {
                success = FALSE;
            }

            if (success) {
                Fits _tmp;
                if (!_tmp.OpenFITS(funcargs[0].svalue->c_str())) {
                    success = false;
                } else {
                    if (_tmp.ReadFitsExtensionHeader(extension, true) > 0) {
                        _tmp.getHeaderInformation();
                            switch (_tmp.extensionType) {
                            case TABLE:
                            case BINTABLE: {
                                rv = ReadFITSBinTable(funcargs[0].toString().c_str(), extension, 0);
                                if (rv.type == typeUnknown) {
                                    success = false;
                                } else {
                                }
                                }
                                break;
                            default:
                                // IMAGE, EMPTY, UNKNOWN
                                for (i = 2, j = 0; i < nargs; i++, j++) {
                                    x[j] = funcargs[i].lvalue;
                                }
                                rv.type = typeFits;
                                rv.fvalue = CreateFits();
                                if (extension == 0) {
                                    success = rv.fvalue->ReadFITS(funcargs[0].svalue->c_str(), x[0], x[1], x[2], x[3], x[4], x[5]);
                                } else {
                                    success = rv.fvalue->ReadFITSExtension(funcargs[0].svalue->c_str(), extension, x[0], x[1], x[2], x[3], x[4], x[5]);
                                }
                                break;
                            }
                    } else {
                        success = false;
                    }
                    _tmp.CloseFITS();
                }
            }
            }
            break;

/************************
 ***  multigauss2dfit ***
 ************************/
        case 177: {
            double chisq;
            int ngauss;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[2].fvalue);
            ngauss = (rv.fvalue->Nelements() - 2) / 3;
            chisq = multigauss2dfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, ngauss);

            if (nargs == 4) {
                dpuser_vars[*funcargs[3].svalue] = chisq;
//                variables[funcargs[3].lvalue].type = typeDbl;
//                variables[funcargs[3].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***     sincfit      ***
 ************************/
        case 178: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[3].fvalue);
            chisq = sincfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***      rebin1d     ***
 ************************/
        case 179:
            rv.type = typeFits;
            rv.clone(funcargs[0]);
            if (nargs == 4)
                rv.fvalue->rebin1d(funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            else
                rv.fvalue->rebin1d(*funcargs[4].fvalue, funcargs[1].dvalue, funcargs[2].dvalue, funcargs[3].dvalue);
            break;

/************************
 ***      velmap      ***
 ************************/
        case 180: {
            double threshold = 0.0;
            int method = 0;

            if (nargs == 4) threshold = funcargs[3].dvalue;
            if (function_options == 2) method = 1;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->velmap(*funcargs[0].fvalue, funcargs[1].dvalue, funcargs[2].dvalue, threshold, method);
            }
            break;

/************************
 ***      fxcor       ***
 ************************/
        case 181:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = fxcor(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, 3);
            break;

/************************
 ***     correlmap    ***
 ************************/
        case 182:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = correlmap(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, 0);
            break;

/************************
 ***     longslit     ***
 ************************/
        case 183:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            if (nargs == 5) {
                success = longslit(*rv.fvalue, *funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue);
            } else {
                success = longslit(*rv.fvalue, *funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue, funcargs[5].dvalue);
            }
            break;

/************************
 ***   evalvelmap    ***
 ************************/
        case 184: {
            Fits line, xvalues, fitparams;
            int x, y;

            rv.type = typeFits;
            rv.clone(funcargs[1]);
            dpProgress(-funcargs[1].fvalue->Naxis(1), "evalvelmap");
            abszissaGenerate(xvalues, *funcargs[1].fvalue, 3);
            funcargs[1].fvalue->extractRange(line, 1, 1, 1, 1, -1, -1);
            for (x = 1; x <= funcargs[1].fvalue->Naxis(1); x++) {
                for (y = 1; y <= funcargs[1].fvalue->Naxis(2); y++) {
                    funcargs[0].fvalue->extractRange(fitparams, x, x, y, y, -1, -1);
                    fitparams.setType(R8);
                    fitparams.r8data[0] = 0.0;
                    evaluate_gauss(line, xvalues, fitparams);
                    rv.fvalue->setRange(line, x, x, y, y, -1, -1);
                }
                dpProgress(x, "evalvelmap");
            }
            }
            break;

/************************
 ***      sinfit      ***
 ************************/
        case 185: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[3].fvalue);
            if (rv.fvalue->Nelements() == 3) {
                chisq = sinfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);
            } else if (rv.fvalue->Nelements() == 2) {
                chisq = sinfit2(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);
            }
            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***    indexbase     ***
 ************************/
        case 186:
            rv.type = typeCon;
            rv.lvalue = indexBase;
            break;

/************************
 ***     voronoi      ***
 ************************/
        case 187:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            voronoi(*funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue, funcargs[3].dvalue, *rv.fvalue, function_options);
            break;

/************************
 *** gauss2dsimplefit ***
 ************************/
        case 188: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            chisq = gauss2dsimplefit(*rv.fvalue, *funcargs[0].fvalue, (int)(funcargs[1].dvalue + .5), (int)(funcargs[2].dvalue + .5), (int)(funcargs[3].dvalue + .5));

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***     transpoly    ***
 ************************/
        case 189: {
            double *xref = NULL, *yref = NULL, *xim = NULL, *yim = NULL, *xerror = NULL, *yerror = NULL;
            double SY[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double SX[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            int i, llen, ncoords;

            llen = funcargs[0].fvalue->Naxis(2);
            if (llen < 6) {
                yyerror("Must have at least 6 reference sources");
                success = FALSE;
                break;
            }
            if ((funcargs[0].fvalue->Naxis(1) != 2) || (funcargs[1].fvalue->Naxis(1) != 2)) {
                yyerror("Input matrices are not of correct size: Must be 2xn");
                success = FALSE;
                break;
            }
            if (funcargs[0].fvalue->Naxis(2) != funcargs[1].fvalue->Naxis(2)) {
                yyerror("The two reference lists do not contain the same number of sources");
                success = FALSE;
                break;
            }

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = rv.fvalue->create(4, 6, R8);
            if (success) {
                xref = (double *)malloc(llen * sizeof(double));
                yref = (double *)malloc(llen * sizeof(double));
                xim = (double *)malloc(llen * sizeof(double));
                yim = (double *)malloc(llen * sizeof(double));
                xerror = (double *)malloc(llen * sizeof(double));
                yerror = (double *)malloc(llen * sizeof(double));

                if ((xref == NULL) || (yref == NULL) || (xim == NULL) || (yim == NULL) || (xerror == NULL) || (yerror == NULL)) {
                    if (xref != NULL) free(xref);
                    if (yref != NULL) free(yref);
                    if (xim != NULL) free(xim);
                    if (yim != NULL) free(yim);
                    if (xerror != NULL) free(xerror);
                    if (yerror != NULL) free(yerror);
                    success = FALSE;
                    break;
                } else {
                    ncoords = 0;
                    for (i = 0; i < llen; i++) {
                        xref[ncoords] = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(0, i));
                        yref[ncoords] = funcargs[0].fvalue->ValueAt(funcargs[0].fvalue->C_I(1, i));
                        xim[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(0, i));
                        yim[ncoords] = funcargs[1].fvalue->ValueAt(funcargs[1].fvalue->C_I(1, i));
                        xerror[ncoords] = funcargs[2].fvalue->ValueAt(funcargs[2].fvalue->C_I(0, i));
                        yerror[ncoords] = funcargs[2].fvalue->ValueAt(funcargs[2].fvalue->C_I(1, i));
                        if ((xim[ncoords] == -1.) || (yim[ncoords] == -1.) || (xref[ncoords] == -1.) || (yref[ncoords] == -1.)) ncoords--;
                        ncoords++;
                    }
                    success = trans_matrix_errors(ncoords, 6, xref, yref, xim, yim, SX, SY, xerror, yerror);
                }
                if (success) {
                    dp_output("transformation matrix is:\nx = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\ny = %5g + %5gx + %5gy + %5gxy + %5gx^2 + %5gy^2\n", SX[5], SX[0], SX[1], SX[4], SX[2], SX[3], SY[5], SY[0], SY[1], SY[4], SY[2], SY[3]);
                    rv.fvalue->r8data[rv.fvalue->F_I(1,1)] = SX[5];
                    rv.fvalue->r8data[rv.fvalue->F_I(1,2)] = SX[0];
                    rv.fvalue->r8data[rv.fvalue->F_I(1,3)] = SX[1];
                    rv.fvalue->r8data[rv.fvalue->F_I(1,4)] = SX[4];
                    rv.fvalue->r8data[rv.fvalue->F_I(1,5)] = SX[2];
                    rv.fvalue->r8data[rv.fvalue->F_I(1,6)] = SX[3];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,1)] = SY[5];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,2)] = SY[0];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,3)] = SY[1];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,4)] = SY[4];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,5)] = SY[2];
                    rv.fvalue->r8data[rv.fvalue->F_I(2,6)] = SY[3];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,1)] = xerror[5];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,2)] = xerror[0];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,3)] = xerror[1];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,4)] = xerror[4];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,5)] = xerror[2];
                    rv.fvalue->r8data[rv.fvalue->F_I(3,6)] = xerror[3];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,1)] = yerror[5];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,2)] = yerror[0];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,3)] = yerror[1];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,4)] = yerror[4];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,5)] = yerror[2];
                    rv.fvalue->r8data[rv.fvalue->F_I(4,6)] = yerror[3];
                }
            }
            free(xref);
            free(yref);
            free(xim);
            free(yim);
            free(xerror);
            free(yerror);
            }
            break;

/************************
 ***      strtrim     ***
 ************************/
        case 190:
            if (funcargs[0].type == typeStrarr) {
                int i;

                rv.type = typeStrarr;
                rv.clone(funcargs[0]);

                for (i = 0; i < rv.arrvalue->size(); i++)
                    (*rv.arrvalue)[i].strtrim(2);
            } else {
                rv.type = typeStr;
                switch (funcargs[0].type) {
                    case typeCon:
                        rv.svalue = CreateString(funcargs[0].lvalue);
                        break;
                    case typeDbl:
                        rv.svalue = CreateString(funcargs[0].dvalue);
                        break;
                    case typeCom:
                        rv.svalue = CreateString(*funcargs[0].cvalue);
                        break;
                    case typeStr:
                        rv.clone(funcargs[0]);
                        break;
                    default:
                        rv.svalue = CreateString();
                        break;
                }
                rv.svalue->strtrim(2);
            }
            break;

/************************
 ***       right      ***
 ************************/
        case 191:
            rv.type = typeStr;
            rv.svalue = CreateString();
            *rv.svalue = funcargs[0].svalue->right(funcargs[1].lvalue);
            break;

/************************
 ***        ten       ***
 ************************/
        case 192:
            rv.type = typeDbl;
            rv.dvalue = ten(funcargs[0].dvalue, funcargs[1].dvalue, funcargs[2].dvalue);
            break;

/************************
 ***      primes      ***
 ************************/
        case 193:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            primes(funcargs[0].lvalue, *rv.fvalue);
            break;

/************************
 ***      twodcut     ***
 ************************/
        case 194:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = twodcut(*rv.fvalue, *funcargs[0].fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].lvalue);
            break;

/************************
 ***simplifywhitespace***
 ************************/
        case 195:
            rv.type = typeStr;
            rv.svalue = CreateString();
            *rv.svalue = funcargs[0].svalue->simplifyWhiteSpace();
            break;

/************************
 ***     strsplit     ***
 ************************/
        case 196: {
            char sep = ' ';

            if (nargs == 2) sep = funcargs[1].svalue->c_str()[0];
            rv.type = typeStrarr;
            rv.arrvalue = CreateStringArray();
            *rv.arrvalue = dpStringList::split(sep, *funcargs[0].svalue);
            }
            break;

/************************
 ***     interpol     ***
 ************************/
        case 197:
            rv.clone(funcargs[0]);
            rv.fvalue->rebin1d(*funcargs[1].fvalue, *funcargs[2].fvalue);
            break;

/************************
 ***    sersic2dfit    ***
 ************************/
        case 198: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[2].fvalue);

            chisq = sersic2dfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue);

            if (nargs == 4) {
                dpuser_vars[*funcargs[3].svalue] = chisq;
            }
            }
            break;

/************************
 *** sersic2dsimplefit ***
 ************************/
        case 199: {
            double chisq, fixed_n = -1.0;

            if (nargs == 6) { // n should be fixed
                fixed_n = funcargs[5].toDouble();
            }

            rv.type = typeFits;
            rv.fvalue = CreateFits();

            chisq = sersic2dsimplefit(*rv.fvalue, *funcargs[0].fvalue, (int)(funcargs[1].dvalue + .5), (int)(funcargs[2].dvalue + .5), (int)(funcargs[3].dvalue + .5), fixed_n);

            if (nargs > 4) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
            }
            }
            break;

/************************
 ***    sersicfit    ***
 ************************/
        case 200: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();

            rv.fvalue->copy(*funcargs[3].fvalue);

            chisq = sersicfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
            }
            }
            break;

/************************
 ***      sersic2d    ***
 ************************/
       case 201:
            rv.type = typeFits;
            rv.fvalue = CreateFits();

            success = rv.fvalue->sersic(dpuser_vars["naxis1"].toInt(), dpuser_vars["naxis2"].toInt(),
                    funcargs[0].toDouble(), funcargs[1].toDouble(), funcargs[2].toDouble(), funcargs[3].toDouble(), funcargs[4].toDouble(), funcargs[5].toDouble());
           break;

/************************
 ***      randomg     ***
 ************************/
       case 202:
            rv.type = typeDbl;

            if (nargs == 2) {
                const gsl_rng_type *T;

                gsl_rng_free(gsl_rng_r);
                gsl_rng_default_seed = funcargs[1].toInt();
                T = gsl_rng_default;
                gsl_rng_r = gsl_rng_alloc(T);
            }
            rv.dvalue = gsl_ran_gaussian(gsl_rng_r, funcargs[0].toDouble());
            break;

/************************
 ***        poly      ***
 ************************/
        case 203:
            try {
                dpuserType x = funcargs[0];
                dpuserType c = funcargs[1];
                if (nargs == 2) {
                    long n, m;
                    long order = c.fvalue->Nelements() - 1;

                    rv.deep_copy(x);

                    if (x.type == typeFits) {
                        long ne = x.fvalue->Nelements();
                        rv.fvalue->setType(R8);
                        (*rv.fvalue) = (*c.fvalue)[order];
                        for (m = order - 1; m >= 0; m--) {
                            for (n = 0; n < ne; n++) {
                                rv.fvalue->r8data[n] = rv.fvalue->r8data[n] * (*x.fvalue)[n] + (*c.fvalue)[m];
                            }
                        }
                    } else {
                        double xx;
                        rv.type = typeDbl;
                        if (x.type == typeDbl) xx = x.dvalue;
                        else xx = (double)(x.lvalue);
                        rv.dvalue = (*c.fvalue)[order];
                        for (m = order - 1; m >= 0; m--) {
                            rv.dvalue = rv.dvalue * xx + (*c.fvalue)[m];
                        }
                    }
                } else {
                    dpuserType derivative = funcargs[2];
                    long n, m;
                    int i, d;
                    long order = c.fvalue->Nelements() - 1;

                    if (order < derivative.toInt()) throw dpuserTypeException("poly: The order of the polynomial must be greater than the order of the derivative");
                    double *a = (double *)malloc((order+1) * sizeof(double));

                    rv.deep_copy(x);

                    for (i = 0; i <= order; i++) a[i] = c.fvalue->ValueAt(i);
                    for (d = 0; d < derivative.toInt(); d++) {
                        for (i = 0; i <= order - 1; i++) {
                            a[i] = (i+1) * a[i+1];
                        }
                        order--;
                    }

                    if (x.type == typeFits) {
                        long ne = x.fvalue->Nelements();
                        rv.fvalue->setType(R8);
                        (*rv.fvalue) = a[order];
                        for (m = order - 1; m >= 0; m--) {
                            for (n = 0; n < ne; n++) {
                                rv.fvalue->r8data[n] = rv.fvalue->r8data[n] * (*x.fvalue)[n] + a[m];
                            }
                        }
                    } else {
                        double xx;
                        rv.type = typeDbl;
                        if (x.type == typeDbl) xx = x.dvalue;
                        else xx = (double)(x.lvalue);
                        rv.dvalue = a[order];
                        for (m = order - 1; m >= 0; m--) {
                            rv.dvalue = rv.dvalue * xx + a[m];
                        }
                    }
                    free(a);
                }
            } catch (dpuserTypeException e) {
                dp_output("%s", e.reason());
                success = FALSE;
            }
            break;

/************************
 ***     getbitpix    ***
 ************************/
        case 204:
            rv.type = typeCon;
            rv.lvalue = funcargs[0].fvalue->getType();
            break;

/************************
 ***     isnan        ***
 ************************/
        case 205:
            rv.type = typeCon;
            if (funcargs[0].type == typeDbl) {
                rv.lvalue = std::isnan(funcargs[0].dvalue);
            } else if (funcargs[0].type == typeCom) {
                if ((std::isnan(funcargs[0].cvalue->real()) == 0) &&
                    (std::isnan(funcargs[0].cvalue->imag()) == 0)) {
                    rv.lvalue = 0;
                } else {
                    rv.lvalue = 1;
                }
            }
            break;

/************************
 ***     isinf        ***
 ************************/
        case 206:
            if (funcargs[0].type == typeDbl) {
                rv.type = typeCon;
                rv.lvalue = _ISINF(funcargs[0].dvalue);
            } else if (funcargs[0].type == typeCom) {
                rv.type = typeCon;

                if ((_ISINF(funcargs[0].cvalue->real()) == 0) &&
                    (_ISINF(funcargs[0].cvalue->imag()) == 0)) {
                    /* e.g. complex(2,5) */
                    rv.lvalue = 0;
                } else if ( ((_ISINF(funcargs[0].cvalue->real()) > 0) &&
                            (_ISINF(funcargs[0].cvalue->imag()) < 0)) ||
                            ((_ISINF(funcargs[0].cvalue->real()) < 0) &&
                            (_ISINF(funcargs[0].cvalue->imag()) > 0))) {
                    /* complex(inf, -inf) or complex(-inf, inf)*/
                    rv.type = typeDbl;
                    rv.dvalue = -0.5;
                } else if ((_ISINF(funcargs[0].cvalue->real()) > 0) ||
                           (_ISINF(funcargs[0].cvalue->imag()) > 0)) {
                    /* e.g. complex(inf, 2) or complex(2, inf)*/
                    rv.lvalue = 1;
                } else if ((_ISINF(funcargs[0].cvalue->real()) < 0) ||
                           (_ISINF(funcargs[0].cvalue->imag()) < 0)) {
                    /* e.g. complex(-inf, 2) or complex(2, -inf)*/
                    rv.lvalue = -1;
                }
            }
            break;

/************************
 ***     polyfit2d    ***
 ************************/
        case 207: {
            try {
                if (funcargs[0].fvalue->Naxis(0) != 2) {
                    dpuserTypeException e("ERROR: Data must be two dimensional!");
                    throw e;
                }

                dpuserType  image = funcargs[0],
                            degree = funcargs[1],
                            chisq,
                            rrv,
                            err;

                chisq.type = typeDbl;
                int i = 0, x = 0, y = 0,
                    img_size = image.fvalue->Nelements();
                Fits x_val, y_val, func_val, errors, result;

                // create needed Fits structures
                x_val.create(img_size, 1, I4);
                y_val.create(img_size, 1, I4);
                func_val.create(img_size, 1, R8);
                errors.create(img_size, 1, I1);

                // fill created Fits structures
                for (y = 1; y <= image.fvalue->Naxis(2); y++) {
                    for (x = 1; x <= image.fvalue->Naxis(1); x++) {
                        x_val.i4data[i] = x;
                        y_val.i4data[i] = y;
                        func_val.r8data[i] = image.fvalue->ValueAt(i);
                        errors.i1data[i] = 1;
                        i++;
                    }
                }

                chisq.type = typeDbl;
                chisq.dvalue =  polyfit2d(result, func_val, x_val, y_val, errors, degree.lvalue);

                rv.type = typeFits;
                rv.fvalue = CreateFits();
                rv.fvalue->copy(result);

                if (nargs == 3) {
                    dpuser_vars[*funcargs[2].svalue] = chisq;
//                    variables[funcargs[2].lvalue].type = typeDbl;
//                    variables[funcargs[2].lvalue].dvalue = chisq.dvalue;
                }
            } catch (dpuserTypeException e) {
                dp_output("%s", e.reason());
                success = FALSE;
            }
            }
            break;

/************************
 ***     polyfit2derr ***
 ************************/
        case 208: {
            try {
                if (funcargs[0].fvalue->Naxis(0) != 2) {
                    dpuserTypeException e("ERROR: Data must be two dimensional!");
                    throw e;
                }

                if ((funcargs[2].type == typeFits) &&
                    ((funcargs[0].fvalue->Naxis(1) != funcargs[2].fvalue->Naxis(1)) ||
                     (funcargs[0].fvalue->Naxis(2) != funcargs[2].fvalue->Naxis(2)))) {
                    dpuserTypeException e("ERROR: Data and errors don't have the same size!");
                    throw e;
                }

                dpuserType  image = funcargs[0],
                            degree = funcargs[1],
                            chisq,
                            rrv,
                            errors = funcargs[2];

                chisq.type = typeDbl;

                int i = 0, x = 0, y = 0,
                    img_size = image.fvalue->Nelements();
                Fits x_val, y_val, func_val, result, err;

                // create needed Fits structuresreturn
                x_val.create(img_size, 1, I4);
                y_val.create(img_size, 1, I4);
                func_val.create(img_size, 1, R8);
                err.create(img_size, 1, R8);

                // fill created Fits structures
                for (y = 1; y <= image.fvalue->Naxis(2); y++) {
                    for (x = 1; x <= image.fvalue->Naxis(1); x++) {
                        x_val.i4data[i] = x;
                        y_val.i4data[i] = y;
                        func_val.r8data[i] = image.fvalue->ValueAt(i);
                        if (errors.type == typeFits) {
                            err.r8data[i] = errors.fvalue->ValueAt(i);
                        } else {
                            err.r8data[i] = errors.dvalue;
                        }

                        i++;
                    }
                }

                chisq.type = typeDbl;
                chisq.dvalue =  polyfit2d(result, func_val, x_val, y_val, err, degree.lvalue);

                rv.type = typeFits;
                rv.fvalue = CreateFits();
                rv.fvalue->copy(result);

                if (nargs == 3) {
                    dpuser_vars[*funcargs[2].svalue] = chisq;
//                    variables[funcargs[2].lvalue].type = typeDbl;
//                    variables[funcargs[2].lvalue].dvalue = chisq.dvalue;
                }
            } catch (dpuserTypeException e) {
                dp_output("%s", e.reason());
                success = FALSE;
            }
            }
            break;

/***********************
 ***   interpolate   ***
 ***********************/
        case 209: {
            try {
                if (funcargs[0].fvalue->Naxis(0) != 2) {
                    dpuserTypeException e("ERROR: Data must be two dimensional!");
                    throw e;
                }

                int kernel_size;
                if (nargs == 4) {
                    kernel_size = funcargs[3].lvalue;
                } else {
                    kernel_size = 4;
                }

                rv.type = typeDbl;
                rv.dvalue = funcargs[0].fvalue->interpolate_pixel(funcargs[1].dvalue, funcargs[2].dvalue, kernel_size);
                success = TRUE;
            } catch (dpuserTypeException e) {
                dp_output("%s", e.reason());
                success = FALSE;
            }
            }
            break;

/************************
 ***   radialprofile  ***
 ************************/
        case 210:
            rv.type = typeFits;
            rv.fvalue = CreateFits();

            success = funcargs[0].fvalue->radial_profile(*rv.fvalue, funcargs[1].lvalue, funcargs[2].lvalue);
            break;

/************************
 ***ellipticalprofile ***
 ************************/
        case 211:
            rv.type = typeFits;
            rv.fvalue = CreateFits();

            success = funcargs[0].fvalue->elliptical_profile(*rv.fvalue, funcargs[1].lvalue, funcargs[2].lvalue, funcargs[3].dvalue, funcargs[4].dvalue, funcargs[5].lvalue);
            break;

/************************
 *** multigaussfit    ***
 ************************/
        case 212: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[3].fvalue);
            chisq = multigaussfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue);

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***   evalgaussfit   ***
 ************************/
        case 213:
            rv = funcargs[0];
            if (rv.type == typeFits) {
                evaluate_gauss(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue);
            } else if (rv.type == typeDbl || rv.type == typeCon) {
                rv.dvalue = evaluate_gauss(funcargs[0].toDouble(), *funcargs[1].fvalue);
            }
            break;

/************************
 ***     polyroots    ***
 ************************/
        case 214:
            rv.type = typeFits;
            rv.fvalue = CreateFits();

            if (nargs == 1) {
                success = (polyroots(*funcargs[0].fvalue, *rv.fvalue) >= 0);
            } else {
                success = (polyroots(*funcargs[0].fvalue, *rv.fvalue, funcargs[1].toInt()) >= 0);
            }
            break;

/************************
 ***      xmin        ***
 ************************/
        case 215: {
            int x, y;

            rv.type = typeCon;
            funcargs[0].fvalue->min_pos(&x, &y);
            rv.lvalue = x;
            }
            break;

/************************
 ***      ymin        ***
 ************************/
        case 216: {
            int x, y;

            rv.type = typeCon;
            funcargs[0].fvalue->min_pos(&x, &y);
            rv.lvalue = y;
            }
            break;

/************************
 ***  readfitsall     ***
 ************************/
        case 217: {
#ifdef DPQT
            resetGUIsettings = false;
#endif
            Fits* f = new Fits;
            int count = f->CountExtensions((*funcargs[0].svalue).c_str());
            delete f;

            if (count == -1) {
                yyerror("Unable to open file!\n");
                success = false;
            } else if (count == 0) {
                // read FITS-file without extensions
                rv.type = typeFits;
                rv.fvalue = CreateFits();
                success = rv.fvalue->ReadFITS(funcargs[0].svalue->c_str());
            } else {
                // read FITS-file with extensions
                rv.type = typeDpArr;
                rv.dparrvalue = CreateDpList();
                success = rv.dparrvalue->ReadFITS(*funcargs[0].svalue);
            }
            }
            break;

/************************
 ***   cubequantile   ***
 ************************/
        case 218:
            if (rv.type == typeFits) {
                rv.fvalue = CreateFits();
                success = rv.fvalue->CubeQuantile(*funcargs[0].fvalue, funcargs[1].dvalue);
            } else {
                rv.type = typeFits;
                rv.fvalue = CreateFits();
                success = rv.fvalue->CubeQuantile(funcargs[0].ffvalue->c_str(), funcargs[1].dvalue);
            }
            break;

/************************
 ***     quantile     ***
 ************************/
        case 219:
            rv.type = typeDbl;
            rv.dvalue = funcargs[0].fvalue->get_nth(funcargs[1].dvalue);
            break;

/************************
 *** straightlinefit  ***
 ************************/
        case 220: {
            double chisq;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            chisq = straightlinefit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue, *funcargs[3].fvalue);
            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 *** sersic2dsmoothfit***
 ************************/
        case 221: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[3].fvalue);
            chisq = sersic2dsmoothfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, funcargs[2].dvalue);

            if (nargs == 5) {
                dpuser_vars[*funcargs[4].svalue] = chisq;
//                variables[funcargs[4].lvalue].type = typeDbl;
//                variables[funcargs[4].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 *** sersic2dsmoothsimplefit ***
 ************************/
    case 222: {
            double chisq;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            chisq = sersic2dsmoothsimplefit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, funcargs[5].dvalue, 0.);
            if (nargs == 7) {
                dpuser_vars[*funcargs[6].svalue] = chisq;
//                variables[funcargs[6].lvalue].type = typeDbl;
//                variables[funcargs[6].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***     test2dfit    ***
 ************************/
        case 223: {
            double chisq;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
            rv.fvalue->copy(*funcargs[2].fvalue);
            chisq = test2dfit(*rv.fvalue, *funcargs[0].fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue);

            if (nargs == 4) {
                dpuser_vars[*funcargs[3].svalue] = chisq;
//                variables[funcargs[3].lvalue].type = typeDbl;
//                variables[funcargs[3].lvalue].dvalue = chisq;
            }
            }
            break;

/************************
 ***    bintablecol   ***
 ************************/
        case 224: {
            int column;

            rv.type = typeFits;
            rv.fvalue = CreateFits();
//          rv.fvalue->copy(*funcargs[0].fvalue);
            if (funcargs[1].type == typeStr) {
                column = funcargs[0].fvalue->FindColumnByName(funcargs[1].svalue->c_str());
            } else {
                column = funcargs[1].lvalue;
            }
            if (column < 1) success = FALSE;
            if (success) {
                if (!funcargs[0].fvalue->GetBintableColumn(column, *(rv.fvalue))) success = FALSE;
            }
            }
            break;

/************************
 *** readfitsbintable ***
 ************************/
        case 225: {
            dpuserType col = 0;
            if (nargs == 3) {
                col = funcargs[2];
            }
            rv = ReadFITSBinTable(funcargs[0].toString().c_str(), funcargs[1], col);
            }
            break;

/************************
 ***listfitsextensions***
 ************************/
        case 226: {
            Fits _tmp;
            rv.type = typeStrarr;
            rv.arrvalue = CreateStringArray(_tmp.ListFitsExtensions(funcargs[0].toString().c_str()));
            }
            break;

/************************
 *** listtablecolumns ***
 ************************/
        case 227: {
            int column;
            Fits _tmp;

            rv.type = typeStrarr;
            if (funcargs[1].type == typeStr) {
                column = _tmp.FindExtensionByName(funcargs[0].toString().c_str(), funcargs[1].toString().c_str());
            } else {
                column = funcargs[1].toInt();
            }
            rv.arrvalue = CreateStringArray(_tmp.ListTableColumns(funcargs[0].toString().c_str(), column));
            }
            break;

/************************
 ***       list       ***
 ************************/
        case 228:
            rv.type = typeDpArr;
            rv.dparrvalue = CreateDpList();

            for (int i = 0; i < nargs; i++) {
                dpuserType *toAppend_tmp, *toAppend;
                toAppend_tmp = new dpuserType(funcargs[i]);
                toAppend = new dpuserType;
                switch (funcargs[i].type) {
                    case typeFits:
                        if (isVariable(toAppend_tmp->fvalue)) {
                            toAppend->deep_copy(*toAppend_tmp);
                            rv.dparrvalue->push_back(toAppend);
                            delete toAppend_tmp;
                        } else {
                            deleteFromListOfFits(toAppend_tmp->fvalue);
                            rv.dparrvalue->push_back(toAppend_tmp);
                            delete toAppend;
                        }
                        break;
                    case typeStrarr:
                        if (isVariable(toAppend_tmp->arrvalue)) {
                            toAppend->deep_copy(*toAppend_tmp);
                            rv.dparrvalue->push_back(toAppend);
                            delete toAppend_tmp;
                        } else {
                            deleteFromListOfdpStringArrays(toAppend_tmp->arrvalue);
                            rv.dparrvalue->push_back(toAppend_tmp);
                            delete toAppend;
                        }
                        break;
                    default: break;
                }
            }
            break;

/************************
 ***     where        ***
 ************************/
        case 229: {
            dpint64 count;
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            count = rv.fvalue->where(*funcargs[0].fvalue);
            if (nargs == 2) {
                dpuser_vars[*funcargs[1].svalue].type = typeCon;
                dpuser_vars[*funcargs[1].svalue].lvalue = count;
//                variables[funcargs[1].lvalue].type = typeCon;
//                variables[funcargs[1].lvalue].lvalue = count;
            }
// since the FITS class where method returns C-based index, we have to increment
            if (count > 0) {
						    for (dpint64 i = 0; i < count; i++) {
								    rv.fvalue->i4data[i]++;
								}
						}
        }
            break;

/************************
***      mpfit        ***
************************/
        case 230: {
                double resultvalue;
                rv.type = typeFits;
                rv.fvalue = CreateFits();
//                resultvalue = mpfit_functionstring(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue, *funcargs[3].fvalue, *funcargs[4].svalue);
                resultvalue = mpfit_fit_userstring(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].fvalue, *funcargs[3].fvalue, *funcargs[4].svalue);
                success = (resultvalue >= 0.0);
            }

                break;

/************************
***    evalmpfit      ***
************************/
        case 231: {
                double resultvalue;
                rv.type = typeFits;
                rv.fvalue = CreateFits();
                resultvalue = mpfit_evaluate_userstring(*rv.fvalue, *funcargs[0].fvalue, *funcargs[1].fvalue, *funcargs[2].svalue);
                success = (resultvalue >= 0);
            }

                break;

/************************
***    mpfitvars      ***
************************/
        case 232: {
//                rv.svalue = CreateString(mpfit_find_variables(*funcargs[0].svalue));
            }

                break;

/************************
***     gausspos      ***
************************/
        case 233:
            rv.type = typeFits;
            rv.fvalue = CreateFits();
            success = funcargs[0].fvalue->gausspos(*rv.fvalue, *funcargs[1].fvalue, funcargs[2].lvalue);
            break;

/************************
***     question      ***
************************/
        case 234: {
            rv.type = typeCon;
            rv.lvalue = 1;
#ifdef DPQT
            dpusermutex->lock();
            dpCommandQFitsView("question", funcargs[0].svalue->c_str(), 0);
            // now wait until the dialog has been closed;
            dpusermutex->lock();
            dpusermutex->unlock();
            rv.lvalue = DPQuestion;
#else
            char response[256];
            dp_output("%s (Yes / No) ", funcargs[0].svalue->c_str());
            read_inp(response);
            if (strlen(response) > 0) if (response[0] == 'N' || response[0] == 'n')
                rv.lvalue = 0;
#endif /* DPQT */
            }
            break;

/************************
***      nparams      ***
************************/
        case 235:
            rv.type = typeCon;
            rv.lvalue = nparams;
                break;

/************************
 ***      double       ***
 ************************/
        case 236:
            rv.type = typeDbl;
            if (funcargs[0].type == typeStr) {
                rv.dvalue = atof(funcargs[0].svalue->c_str());
            } else if (funcargs[0].type == typeCon) {
                rv.dvalue = (double)funcargs[0].lvalue;
            } else if (funcargs[0].type == typeCom) {
                rv.dvalue = real(*funcargs[0].cvalue);
            } else if (funcargs[0].type == typeDbl) {
                rv.dvalue = funcargs[0].dvalue;
            } else if (funcargs[0].type == typeFits) {
                rv.clone(funcargs[0]);
                rv.fvalue->setType(R8);
            } else {
                rv.dvalue = 0.0;
            }
            break;

/************************
 ***      pyvar       ***
 ************************/
        case 237:
#ifdef HAS_PYTHON
            rv = getPythonVariable(funcargs[0].svalue->c_str());
            break;
#endif /* HAS_PYTHON */

/************************
 ***       mjd        ***
 ************************/
        case 238: {
            rv.type = typeDbl;
            CJulianDay jd(funcargs[0].toDouble());

            if (nargs == 2) jd.SetJD(funcargs[0].toInt(), funcargs[1].toDouble());
            else if (nargs == 3) jd.SetJD(funcargs[0].toInt(), funcargs[1].toInt(), funcargs[2].lvalue, 0, 0, 0.0);
            else if (nargs == 4) jd.SetJD(funcargs[0].toInt(), funcargs[1].toInt(), funcargs[2].lvalue, funcargs[3].lvalue, 0, 0.0);
            else if (nargs == 5) jd.SetJD(funcargs[0].toInt(), funcargs[1].toInt(), funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, 0.0);
            else if (nargs == 6) {
                if (funcargs[5].type == typeCon) funcargs[5].dvalue = (double)funcargs[5].lvalue;
                jd.SetJD(funcargs[0].toInt(), funcargs[1].toInt(), funcargs[2].lvalue, funcargs[3].lvalue, funcargs[4].lvalue, funcargs[5].dvalue);
            }
            JDStruct mjdbase;
            mjdbase.dFraction = 0.5;
            mjdbase.lNumber = 2400000;
            jd -= mjdbase;
            rv.dvalue = (double)jd;
        }
            break;

/************************
 ***     replace      ***
 ************************/
        case 239:
            rv.clone(funcargs[0]);
            if (rv.type == typeStr) {
                rv.svalue->replace(dpRegExp(*funcargs[1].svalue), *funcargs[2].svalue);
            } else if (rv.type == typeStrarr) {
                for (dpint64 n = 0; n < rv.arrvalue->count(); n++)
                (*rv.arrvalue)[n].replace(dpRegExp(*funcargs[1].svalue), *funcargs[2].svalue);
            } else success = FALSE;
            break;

/************************
 ***      subpixel    ***
 ************************/
        case 240:
            rv.type = typeDbl;
            rv.dvalue = funcargs[0].fvalue->SubPixel(funcargs[1].toDouble(), funcargs[2].toDouble());
            break;

/************************
 ***      distort     ***
 ************************/
        case 241: {
            double nx, ny;
            rv.type = typeFits;
            rv.fvalue = CreateFits(funcargs[0].fvalue->Naxis(1), funcargs[0].fvalue->Naxis(2), 1, R8);
            dpint64 count = 0;
            for (dpint64 y = 1; y <= funcargs[0].fvalue->Naxis(1); y++) {
                for (dpint64 x = 1; x <= funcargs[0].fvalue->Naxis(2); x++) {
                    rv.fvalue->r8data[count] = funcargs[0].fvalue->SubPixel(
                                x + funcargs[1].fvalue->ValueAt(count),
                                y + funcargs[2].fvalue->ValueAt(count)
                            );
                    count++;
                }
            }
        }
            break;

/************************
 ***     worldpos     ***
 ************************/
        case 242: {
            if (funcargs[1].fvalue->Naxis(1) != 2 || funcargs[1].fvalue->Naxis(2) < 1) {
                success = false;
                break;
            }
            double crota2, cd1_1, cd2_1, cd1_2, cd2_2, x, y, xpos, ypos;
            rv.type = typeFits;
            rv.fvalue = CreateFits(2, funcargs[1].fvalue->Naxis(2), 1, R8);
            funcargs[0].fvalue->GetFloatKey("CROTA2", &crota2);
            funcargs[0].fvalue->GetFloatKey("CD1_1", &cd1_1);
            funcargs[0].fvalue->GetFloatKey("CD2_1", &cd2_1);
            funcargs[0].fvalue->GetFloatKey("CD1_2", &cd1_2);
            funcargs[0].fvalue->GetFloatKey("CD2_2", &cd2_2);

            for (int i = 0; i < funcargs[1].fvalue->Naxis(2); i++) {
                x = funcargs[1].fvalue->ValueAt(i * 2);
                y = funcargs[1].fvalue->ValueAt(i * 2 + 1);
                worldpos(x, y, funcargs[0].fvalue->getCRVAL(1),
                     funcargs[0].fvalue->getCRVAL(2),
                     funcargs[0].fvalue->getCRPIX(1),
                     funcargs[0].fvalue->getCRPIX(2),
                     funcargs[0].fvalue->getCDELT(1),
                     funcargs[0].fvalue->getCDELT(2),
                     crota2, cd1_1, cd2_1, cd1_2, cd2_2,
                     funcargs[0].fvalue->crtype,
                     &xpos, &ypos);
                rv.fvalue->r8data[i * 2] = xpos;
                rv.fvalue->r8data[i * 2 + 1] = ypos;
            }
        }
            break;

/************************
 ***      pixpos      ***
 ************************/
       case 243: {
           if (funcargs[1].fvalue->Naxis(1) != 2 || funcargs[1].fvalue->Naxis(2) < 1) {
               success = false;
               break;
           }
           double crota2, cd1_1, cd2_1, cd1_2, cd2_2, x, y, xpos, ypos;
           rv.type = typeFits;
           rv.fvalue = CreateFits(2, funcargs[1].fvalue->Naxis(2), 1, R8);
           funcargs[0].fvalue->GetFloatKey("CROTA2", &crota2);
           funcargs[0].fvalue->GetFloatKey("CD1_1", &cd1_1);
           funcargs[0].fvalue->GetFloatKey("CD2_1", &cd2_1);
           funcargs[0].fvalue->GetFloatKey("CD1_2", &cd1_2);
           funcargs[0].fvalue->GetFloatKey("CD2_2", &cd2_2);

           for (int i = 0; i < funcargs[1].fvalue->Naxis(2); i++) {
               x = funcargs[1].fvalue->ValueAt(i * 2);
               y = funcargs[1].fvalue->ValueAt(i * 2 + 1);
               worldpix(x, y, funcargs[0].fvalue->getCRVAL(1),
                    funcargs[0].fvalue->getCRVAL(2),
                    funcargs[0].fvalue->getCRPIX(1),
                    funcargs[0].fvalue->getCRPIX(2),
                    funcargs[0].fvalue->getCDELT(1),
                    funcargs[0].fvalue->getCDELT(2),
                    crota2, cd1_1, cd2_1, cd1_2, cd2_2,
                    funcargs[0].fvalue->crtype,
                    &xpos, &ypos);
               rv.fvalue->r8data[i * 2] = xpos;
               rv.fvalue->r8data[i * 2 + 1] = ypos;
           }
       }
           break;

/************************
 ***       exec      ***
 ************************/
       case 244: {
          rv.type = typeStrarr;
          rv.arrvalue = CreateStringArray();
          std::shared_ptr<FILE> pipe(popen(funcargs[0].svalue->c_str(), "r"), pclose);
          if (pipe) {
              char buffer[128];
							dpString output;
              while (!feof(pipe.get())) {
                  if (fgets(buffer, 128, pipe.get()) != NULL) {
                        output += buffer;
                  }
              }
    					 *rv.arrvalue = dpStringList::splitcrlf(output);
           }
        }
				break;

/************************
 ***      N/A         ***
 ************************/
        default:
            dp_output("Function %s not implemented.\n", funcs[id].name.c_str());
            success = 0;
            break;
    } /* END switch (id) */

    if (!success) {
        dp_output("%s: ", funcs[id].name.c_str());
        yyerror("Error processing function.\n");
        rv = er;

    }
//  }
//  catch (dpFitsException e) {
//      printf("%s\n", e.reason());
//      rv = er;
//  }
#ifdef DPQT
    for (int i = 0; i < nargs; i++) {
        if (funcs[id].args[i] == (typeId|ANYTHING)) {
            dpUpdateVar(*funcargs[i].svalue);
        }
    }
#endif /* DPQT */
    return rv;




}

