org.eclipse.january.dataset.GeneratedMaths.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.january.dataset.GeneratedMaths.java

Source

/*-
 *******************************************************************************
 * Copyright (c) 2017 Diamond Light Source Ltd.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Peter Chang - initial API and implementation and/or initial documentation
 *******************************************************************************/

package org.eclipse.january.dataset;

import org.apache.commons.math3.complex.Complex;

/**
 * Generated by template/generatefunctions.py
 */
class GeneratedMaths {
    protected static void addFunctionName(final Dataset a, final Dataset b, final Dataset dataset,
            final String fname) {
        dataset.setName(Operations.createFunctionName(fname, a.getName(), b.getName()));
    }

    protected static void addFunctionName(final Dataset dataset, final String fname) {
        dataset.setName(Operations.createFunctionName(fname, dataset.getName()));
    }

    protected static void addBinaryOperatorName(final Dataset a, final Dataset b, final Dataset dataset,
            final String oname) {
        dataset.setName(Operations.createBinaryOperationName(oname, a.getName(), b.getName()));
    }

    protected static long toLong(double d) {
        return (long) d;
    }

    // Start of generated code
    /**
     * add operator
     * @param a
     * @param b
     * @return a + b, addition of a and b
     */
    public static Dataset add(final Object a, final Object b) {
        return add(a, b, null);
    }

    /**
     * add operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a + b, addition of a and b
     */
    public static Dataset add(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(iax + ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (iax + ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(iax + ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (iax + ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(iax + ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (iax + ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(iax + ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (iax + ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax + ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax + ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax + ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax + ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax + ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax + ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax + ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax + ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax + ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax + ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax + ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax + ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax + ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax + ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax + ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax + ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax + ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax + ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax + ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax + ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax + ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax + ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax + ibx);
                    oy = (float) (iay + iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax + ibx);
                    oy = (float) (iay + iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax + ibx);
                    oy = (float) (iay + iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax + ibx);
                    oy = (iay + iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax + ibx);
                    oy = (iay + iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax + ibx);
                    oy = (iay + iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "add supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "+");
        return result;
    }

    /**
     * subtract operator
     * @param a
     * @param b
     * @return a - b, subtraction of a by b
     */
    public static Dataset subtract(final Object a, final Object b) {
        return subtract(a, b, null);
    }

    /**
     * subtract operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a - b, subtraction of a by b
     */
    public static Dataset subtract(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(iax - ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (iax - ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(iax - ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (iax - ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(iax - ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (iax - ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(iax - ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (iax - ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax - ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax - ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax - ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax - ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax - ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax - ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax - ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax - ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax - ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax - ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax - ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax - ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax - ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax - ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax - ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax - ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax - ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax - ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax - ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax - ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax - ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax - ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax - ibx);
                    oy = (float) (iay - iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax - ibx);
                    oy = (float) (iay - iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax - ibx);
                    oy = (float) (iay - iby);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax - ibx);
                    oy = (iay - iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax - ibx);
                    oy = (iay - iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax - ibx);
                    oy = (iay - iby);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "subtract supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "-");
        return result;
    }

    /**
     * multiply operator
     * @param a
     * @param b
     * @return a * b, product of a and b
     */
    public static Dataset multiply(final Object a, final Object b) {
        return multiply(a, b, null);
    }

    /**
     * multiply operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a * b, product of a and b
     */
    public static Dataset multiply(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(iax * ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (iax * ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(iax * ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (iax * ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(iax * ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (iax * ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(iax * ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (iax * ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax * ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax * ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax * ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax * ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax * ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax * ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax * ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax * ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax * ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax * ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax * ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax * ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax * ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax * ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax * ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax * ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax * ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax * ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax * ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax * ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax * ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax * ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax * ibx - iay * iby);
                    oy = (float) (iax * iby + iay * ibx);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax * ibx - iay * iby);
                    oy = (float) (iax * iby + iay * ibx);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (iax * ibx - iay * iby);
                    oy = (float) (iax * iby + iay * ibx);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax * ibx - iay * iby);
                    oy = (iax * iby + iay * ibx);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax * ibx - iay * iby);
                    oy = (iax * iby + iay * ibx);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    ox = (iax * ibx - iay * iby);
                    oy = (iax * iby + iay * ibx);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "multiply supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "*");
        return result;
    }

    /**
     * divide operator
     * @param a
     * @param b
     * @return a / b, division of a by b
     */
    public static Dataset divide(final Object a, final Object b) {
        return divide(a, b, null);
    }

    /**
     * divide operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a / b, division of a by b
     */
    public static Dataset divide(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (ibx == 0 ? 0 : iax / ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(ibx == 0 ? 0 : iax / ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (ibx == 0 ? 0 : iax / ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (ibx == 0 ? 0 : iax / ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "divide supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "/");
        return result;
    }

    /**
     * dividez operator
     * @param a
     * @param b
     * @return a / b, division of a by b
     */
    public static Dataset dividez(final Object a, final Object b) {
        return dividez(a, b, null);
    }

    /**
     * dividez operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a / b, division of a by b
     */
    public static Dataset dividez(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (ibx == 0 ? 0 : iax / ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(ibx == 0 ? 0 : iax / ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (ibx == 0 ? 0 : iax / ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (ibx == 0 ? 0 : iax / ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax / ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax / ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax / ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax / ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax / ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (ibx == 0 ? 0 : iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (ibx == 0 ? 0 : iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (ibx == 0 ? 0 : iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (ibx == 0 ? 0 : iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (ibx == 0 ? 0 : iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (ibx == 0 && iby == 0) {
                        ox = 0;
                        oy = 0;
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "dividez supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "/");
        return result;
    }

    /**
     * divideTowardsFloor operator
     * @param a
     * @param b
     * @return a / b, division of a by b but rounded towards negative infinity
     */
    public static Dataset divideTowardsFloor(final Object a, final Object b) {
        return divideTowardsFloor(a, b, null);
    }

    /**
     * divideTowardsFloor operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a / b, division of a by b but rounded towards negative infinity
     */
    public static Dataset divideTowardsFloor(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (byte) toLong(iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (byte) (iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (short) toLong(iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (short) (iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = toLong(iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (int) toLong(iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    if (ibx == 0) {
                        ox = 0;
                    } else {
                        ox = (int) (iax / ibx);
                        if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                            ox--;
                        }
                    }
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (byte) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (byte) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (short) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (short) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) toLong(iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) toLong(iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        if (ibx == 0) {
                            ox = 0;
                        } else {
                            ox = (int) (iax / ibx);
                            if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                ox--;
                            }
                        }
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            if (ibx == 0) {
                                ox = 0;
                            } else {
                                ox = (int) (iax / ibx);
                                if (iax != ox * ibx && ((iax < 0) ^ (ibx < 0))) {
                                    ox--;
                                }
                            }
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax / ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax / ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax / ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax / ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax / ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    float q;
                    float den;
                    if (iby == 0) {
                        ox = (float) (iax / ibx);
                        oy = (float) (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (float) (iay / iby);
                        oy = (float) (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (float) (ibx / iby);
                        den = (float) (ibx * q + iby);
                        ox = (float) ((iax * q + iay) / den);
                        oy = (float) ((iay * q - ibx) / den);
                    } else {
                        q = (float) (iby / ibx);
                        den = (float) (iby * q + ibx);
                        ox = (float) ((iay * q + iax) / den);
                        oy = (float) ((iay - iax * q) / den);
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    double q;
                    double den;
                    if (iby == 0) {
                        ox = (iax / ibx);
                        oy = (iay / ibx);
                    } else if (ibx == 0) {
                        ox = (iay / iby);
                        oy = (-iax / iby);
                    } else if (Math.abs(ibx) < Math.abs(iby)) {
                        q = (ibx / iby);
                        den = (ibx * q + iby);
                        ox = ((iax * q + iay) / den);
                        oy = ((iay * q - ibx) / den);
                    } else {
                        q = (iby / ibx);
                        den = (iby * q + ibx);
                        ox = ((iay * q + iax) / den);
                        oy = ((iay - iax * q) / den);
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "divideTowardsFloor supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "/");
        return result;
    }

    /**
     * power operator
     * @param a
     * @param b
     * @return a ** b, raise a to power of b
     */
    public static Dataset power(final Object a, final Object b) {
        return power(a, b, null);
    }

    /**
     * power operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a ** b, raise a to power of b
     */
    public static Dataset power(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(Math.pow(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) toLong(Math.pow(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(Math.pow(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) toLong(Math.pow(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(Math.pow(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = toLong(Math.pow(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(Math.pow(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) toLong(Math.pow(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.pow(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.pow(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.pow(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.pow(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.pow(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.pow(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.pow(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.pow(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (Math.pow(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (float) (Math.pow(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (Math.pow(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (Math.pow(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.pow(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.pow(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.pow(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.pow(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(iax, iay).pow(new Complex(ibx, iby));
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "power supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "**");
        return result;
    }

    /**
     * remainder operator
     * @param a
     * @param b
     * @return a % b, remainder of division of a by b
     */
    public static Dataset remainder(final Object a, final Object b) {
        return remainder(a, b, null);
    }

    /**
     * remainder operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a % b, remainder of division of a by b
     */
    public static Dataset remainder(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) (ibx == 0 ? 0 : iax % ibx);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(ibx == 0 ? 0 : iax % ibx);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = (ibx == 0 ? 0 : iax % ibx);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) (ibx == 0 ? 0 : iax % ibx);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (ibx == 0 ? 0 : iax % ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (ibx == 0 ? 0 : iax % ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (ibx == 0 ? 0 : iax % ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (ibx == 0 ? 0 : iax % ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (ibx == 0 ? 0 : iax % ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (ibx == 0 ? 0 : iax % ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (ibx == 0 ? 0 : iax % ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (iax % ibx);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (iax % ibx);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (iax % ibx);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (iax % ibx);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (iax % ibx);
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (iax % ibx);
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax % ibx);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "remainder supports integer, compound integer, real, compound real datasets only");
        }

        addBinaryOperatorName(da, db, result, "%");
        return result;
    }

    /**
     * maximum operator
     * @param a
     * @param b
     * @return return maximum of a and b
     */
    public static Dataset maximum(final Object a, final Object b) {
        return maximum(a, b, null);
    }

    /**
     * maximum operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return return maximum of a and b
     */
    public static Dataset maximum(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(Math.max(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) toLong(Math.max(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(Math.max(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) toLong(Math.max(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(Math.max(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = toLong(Math.max(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(Math.max(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) toLong(Math.max(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.max(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.max(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.max(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.max(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.max(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.max(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.max(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.max(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (Math.max(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (float) (Math.max(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (Math.max(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (Math.max(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.max(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.max(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.max(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.max(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.max(iax, ibx));
                        oy = (float) (Math.max(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.max(iax, ibx));
                        oy = (float) (Math.max(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.max(iax, ibx));
                        oy = (float) (Math.max(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.max(iax, ibx));
                        oy = (Math.max(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.max(iax, ibx));
                        oy = (Math.max(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.max(iax, ibx));
                        oy = (Math.max(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "maximum supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "maximum");
        return result;
    }

    /**
     * minimum operator
     * @param a
     * @param b
     * @return return minimum of a and b
     */
    public static Dataset minimum(final Object a, final Object b) {
        return minimum(a, b, null);
    }

    /**
     * minimum operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return return minimum of a and b
     */
    public static Dataset minimum(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    byte ox;
                    ox = (byte) toLong(Math.min(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    byte ox;
                    ox = (byte) toLong(Math.min(iax, ibx));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    short ox;
                    ox = (short) toLong(Math.min(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    short ox;
                    ox = (short) toLong(Math.min(iax, ibx));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    long ox;
                    ox = toLong(Math.min(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    long ox;
                    ox = toLong(Math.min(iax, ibx));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    int ox;
                    ox = (int) toLong(Math.min(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    int ox;
                    ox = (int) toLong(Math.min(iax, ibx));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) toLong(Math.min(iax, ibx));
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) toLong(Math.min(iax, ibx));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) toLong(Math.min(iax, ibx));
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) toLong(Math.min(iax, ibx));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = toLong(Math.min(iax, ibx));
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = toLong(Math.min(iax, ibx));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) toLong(Math.min(iax, ibx));
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) toLong(Math.min(iax, ibx));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    float ox;
                    ox = (float) (Math.min(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    float ox;
                    ox = (float) (Math.min(iax, ibx));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    double ox;
                    ox = (Math.min(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long iax = it.aLong;
                    final long ibx = it.bLong;
                    double ox;
                    ox = (Math.min(iax, ibx));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        float ox;
                        ox = (float) (Math.min(iax, ibx));
                        oaf32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (float) (Math.min(iax, ibx));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        final double ibx = it.bDouble;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        double iax = it.aDouble;
                        double ibx = it.bDouble;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementDoubleAbs(it.aIndex + j);
                            ibx = db.getElementDoubleAbs(it.bIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        double ox;
                        ox = (Math.min(iax, ibx));
                        oaf64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (Math.min(iax, ibx));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.min(iax, ibx));
                        oy = (float) (Math.min(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.min(iax, ibx));
                        oy = (float) (Math.min(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    float ox;
                    float oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (float) (iax);
                        oy = (float) (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (float) (ibx);
                        oy = (float) (iby);
                    } else {
                        ox = (float) (Math.min(iax, ibx));
                        oy = (float) (Math.min(iay, iby));
                    }
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iay = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.min(iax, ibx));
                        oy = (Math.min(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else if (bs == 1) {
                final double iby = 0;
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.min(iax, ibx));
                        oy = (Math.min(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double iax = it.aDouble;
                    final double ibx = it.bDouble;
                    final double iay = da.getElementDoubleAbs(it.aIndex + 1);
                    final double iby = db.getElementDoubleAbs(it.bIndex + 1);
                    double ox;
                    double oy;
                    if (Double.isNaN(iax) || Double.isNaN(iay)) {
                        ox = (iax);
                        oy = (iay);
                    } else if (Double.isNaN(ibx) || Double.isNaN(iby)) {
                        ox = (ibx);
                        oy = (iby);
                    } else {
                        ox = (Math.min(iax, ibx));
                        oy = (Math.min(iay, iby));
                    }
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "minimum supports integer, compound integer, real, compound real, complex datasets only");
        }

        addBinaryOperatorName(da, db, result, "minimum");
        return result;
    }

    /**
     * bitwiseAnd operator
     * @param a
     * @param b
     * @return a & b, bitwise AND of a and b
     */
    public static Dataset bitwiseAnd(final Object a, final Object b) {
        return bitwiseAnd(a, b, null);
    }

    /**
     * bitwiseAnd operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a & b, bitwise AND of a and b
     */
    public static Dataset bitwiseAnd(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) (iax & ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) (iax & ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = (iax & ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) (iax & ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax & ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax & ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax & ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax & ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax & ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax & ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax & ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax & ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax & ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax & ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax & ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax & ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax & ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax & ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax & ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax & ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax & ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax & ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax & ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax & ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax & ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax & ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax & ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax & ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax & ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax & ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax & ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax & ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("bitwiseAnd supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, "&");
        return result;
    }

    /**
     * bitwiseOr operator
     * @param a
     * @param b
     * @return a | b, bitwise inclusive OR of a and b
     */
    public static Dataset bitwiseOr(final Object a, final Object b) {
        return bitwiseOr(a, b, null);
    }

    /**
     * bitwiseOr operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a | b, bitwise inclusive OR of a and b
     */
    public static Dataset bitwiseOr(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) (iax | ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) (iax | ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = (iax | ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) (iax | ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax | ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax | ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax | ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax | ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax | ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax | ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax | ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax | ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax | ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax | ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax | ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax | ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax | ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax | ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax | ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax | ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax | ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax | ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax | ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax | ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax | ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax | ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax | ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax | ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax | ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax | ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax | ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax | ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("bitwiseOr supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, "|");
        return result;
    }

    /**
     * bitwiseXor operator
     * @param a
     * @param b
     * @return a ^ b, bitwise exclusive OR of a and b
     */
    public static Dataset bitwiseXor(final Object a, final Object b) {
        return bitwiseXor(a, b, null);
    }

    /**
     * bitwiseXor operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a ^ b, bitwise exclusive OR of a and b
     */
    public static Dataset bitwiseXor(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) (iax ^ ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) (iax ^ ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = (iax ^ ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) (iax ^ ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax ^ ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax ^ ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax ^ ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax ^ ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax ^ ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax ^ ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax ^ ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax ^ ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax ^ ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax ^ ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax ^ ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax ^ ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax ^ ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax ^ ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax ^ ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax ^ ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax ^ ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax ^ ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax ^ ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax ^ ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax ^ ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax ^ ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax ^ ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax ^ ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax ^ ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax ^ ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax ^ ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax ^ ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("bitwiseXor supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, "^");
        return result;
    }

    /**
     * leftShift operator
     * @param a
     * @param b
     * @return a << b, bitwise left shift of a by b
     */
    public static Dataset leftShift(final Object a, final Object b) {
        return leftShift(a, b, null);
    }

    /**
     * leftShift operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a << b, bitwise left shift of a by b
     */
    public static Dataset leftShift(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) (iax << ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) (iax << ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = (iax << ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) (iax << ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax << ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax << ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax << ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax << ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax << ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax << ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax << ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax << ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax << ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax << ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax << ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax << ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax << ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax << ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax << ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax << ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax << ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax << ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax << ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax << ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax << ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax << ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax << ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax << ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax << ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax << ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax << ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax << ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("leftShift supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, "<<");
        return result;
    }

    /**
     * rightShift operator
     * @param a
     * @param b
     * @return a >> b, bitwise right shift of a by b
     */
    public static Dataset rightShift(final Object a, final Object b) {
        return rightShift(a, b, null);
    }

    /**
     * rightShift operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a >> b, bitwise right shift of a by b
     */
    public static Dataset rightShift(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) (iax >> ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) (iax >> ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = (iax >> ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) (iax >> ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax >> ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax >> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax >> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax >> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) (iax >> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) (iax >> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) (iax >> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax >> ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax >> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax >> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax >> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) (iax >> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) (iax >> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) (iax >> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax >> ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax >> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax >> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = (iax >> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (iax >> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = (iax >> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (iax >> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax >> ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax >> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax >> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax >> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) (iax >> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) (iax >> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) (iax >> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("rightShift supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, ">>");
        return result;
    }

    /**
     * unsignedRightShift operator
     * @param a
     * @param b
     * @return a >>> b, bitwise right shift of a by b with zeros added
     */
    public static Dataset unsignedRightShift(final Object a, final Object b) {
        return unsignedRightShift(a, b, null);
    }

    /**
     * unsignedRightShift operator
     * @param a
     * @param b
     * @param o output can be null - in which case, a new dataset is created
     * @return a >>> b, bitwise right shift of a by b with zeros added
     */
    public static Dataset unsignedRightShift(final Object a, final Object b, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final Dataset db = b instanceof Dataset ? (Dataset) b : DatasetFactory.createFromObject(b);
        final BroadcastIterator it = BroadcastIterator.createIterator(da, db, o, true);
        it.setOutputDouble(false);
        final long unsignedMask;
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int bs = db.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            unsignedMask = 0xffL; {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                byte ox;
                ox = (byte) ((unsignedMask & iax) >>> ibx);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            unsignedMask = 0xffffL; {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                short ox;
                ox = (short) ((unsignedMask & iax) >>> ibx);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            unsignedMask = 0xffffffffffffffffL; {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                long ox;
                ox = ((unsignedMask & iax) >>> ibx);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            unsignedMask = 0xffffffffL; {
            while (it.hasNext()) {
                final long iax = it.aLong;
                final long ibx = it.bLong;
                int ox;
                ox = (int) ((unsignedMask & iax) >>> ibx);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            unsignedMask = 0xffL;
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) ((unsignedMask & iax) >>> ibx);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) ((unsignedMask & iax) >>> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) ((unsignedMask & iax) >>> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        byte ox;
                        ox = (byte) ((unsignedMask & iax) >>> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (byte) ((unsignedMask & iax) >>> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        byte ox;
                        ox = (byte) ((unsignedMask & iax) >>> ibx);
                        oai8data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (byte) ((unsignedMask & iax) >>> ibx);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            unsignedMask = 0xffffL;
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) ((unsignedMask & iax) >>> ibx);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) ((unsignedMask & iax) >>> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) ((unsignedMask & iax) >>> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        short ox;
                        ox = (short) ((unsignedMask & iax) >>> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (short) ((unsignedMask & iax) >>> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        short ox;
                        ox = (short) ((unsignedMask & iax) >>> ibx);
                        oai16data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (short) ((unsignedMask & iax) >>> ibx);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            unsignedMask = 0xffffffffffffffffL;
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = ((unsignedMask & iax) >>> ibx);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = ((unsignedMask & iax) >>> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = ((unsignedMask & iax) >>> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        long ox;
                        ox = ((unsignedMask & iax) >>> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = ((unsignedMask & iax) >>> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        long ox;
                        ox = ((unsignedMask & iax) >>> ibx);
                        oai64data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = ((unsignedMask & iax) >>> ibx);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            unsignedMask = 0xffffffffL;
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) ((unsignedMask & iax) >>> ibx);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1 || as < bs) {
                {
                    while (it.hasNext()) {
                        final long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) ((unsignedMask & iax) >>> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) ((unsignedMask & iax) >>> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else if (bs == 1 || as > bs) {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        final long ibx = it.bLong;
                        int ox;
                        ox = (int) ((unsignedMask & iax) >>> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ox = (int) ((unsignedMask & iax) >>> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        long iax = it.aLong;
                        long ibx = it.bLong;
                        int ox;
                        ox = (int) ((unsignedMask & iax) >>> ibx);
                        oai32data[it.oIndex] = ox;
                        for (int j = 1; j < is; j++) {
                            iax = da.getElementLongAbs(it.aIndex + j);
                            ibx = db.getElementLongAbs(it.bIndex + j);
                            ox = (int) ((unsignedMask & iax) >>> ibx);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "unsignedRightShift supports integer, compound integer datasets only");
        }

        addBinaryOperatorName(da, db, result, ">>>");
        return result;
    }

    /**
     * bitwiseInvert - ~a, bitwise invert (or NOT) each element
     * @param a
     * @return dataset
     */
    public static Dataset bitwiseInvert(final Object a) {
        return bitwiseInvert(a, null);
    }

    /**
     * bitwiseInvert - ~a, bitwise invert (or NOT) each element
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset bitwiseInvert(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true, true, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData(); {
            while (it.hasNext()) {
                final long ix = it.aLong;
                byte ox;
                ox = (byte) toLong(~ix);
                oi8data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData(); {
            while (it.hasNext()) {
                final long ix = it.aLong;
                short ox;
                ox = (short) toLong(~ix);
                oi16data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData(); {
            while (it.hasNext()) {
                final long ix = it.aLong;
                long ox;
                ox = toLong(~ix);
                oi64data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData(); {
            while (it.hasNext()) {
                final long ix = it.aLong;
                int ox;
                ox = (int) toLong(~ix);
                oi32data[it.oIndex] = ox;
            }
        }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(~ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(~ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(~ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(~ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(~ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(~ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(~ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(~ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(~ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(~ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(~ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(~ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("bitwiseInvert supports integer, compound integer datasets only");
        }

        addFunctionName(result, "bitwiseInvert");
        return result;
    }

    /**
     * sin - evaluate the sine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset sin(final Object a) {
        return sin(a, null);
    }

    /**
     * sin - evaluate the sine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset sin(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.sin(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.sin(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.sin(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.sin(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.sin(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.sin(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.sin(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.sin(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sin(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sin(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sin(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sin(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sin(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sin(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sin(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sin(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sin(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sin(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sin(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sin(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sin(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sin(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sin(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sin(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.sin(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.sin(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.sin(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.sin(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sin(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sin(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sin(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sin(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sin(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sin(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sin(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sin(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.sin(ix) * Math.cosh(iy));
                    oy = (float) (Math.cos(ix) * Math.sinh(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.sin(ix) * Math.cosh(iy));
                    oy = (float) (Math.cos(ix) * Math.sinh(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.sin(ix) * Math.cosh(iy));
                    oy = (Math.cos(ix) * Math.sinh(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.sin(ix) * Math.cosh(iy));
                    oy = (Math.cos(ix) * Math.sinh(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "sin supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "sin");
        return result;
    }

    /**
     * cos - evaluate the cosine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset cos(final Object a) {
        return cos(a, null);
    }

    /**
     * cos - evaluate the cosine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset cos(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.cos(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.cos(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.cos(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.cos(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.cos(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.cos(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.cos(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.cos(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cos(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cos(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cos(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cos(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cos(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cos(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cos(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cos(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cos(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cos(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cos(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cos(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cos(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cos(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cos(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cos(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.cos(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.cos(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.cos(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.cos(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cos(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cos(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cos(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cos(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cos(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cos(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cos(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cos(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.cos(ix) * Math.cosh(iy));
                    oy = (float) (-Math.sin(ix) * Math.sinh(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.cos(ix) * Math.cosh(iy));
                    oy = (float) (-Math.sin(ix) * Math.sinh(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.cos(ix) * Math.cosh(iy));
                    oy = (-Math.sin(ix) * Math.sinh(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.cos(ix) * Math.cosh(iy));
                    oy = (-Math.sin(ix) * Math.sinh(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "cos supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "cos");
        return result;
    }

    /**
     * tan - evaluate the tangent function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset tan(final Object a) {
        return tan(a, null);
    }

    /**
     * tan - evaluate the tangent function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset tan(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.tan(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.tan(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.tan(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.tan(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.tan(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.tan(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.tan(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.tan(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.tan(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.tan(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.tan(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.tan(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.tan(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.tan(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.tan(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.tan(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.tan(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.tan(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.tan(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.tan(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.tan(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.tan(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.tan(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.tan(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.tan(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.tan(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.tan(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.tan(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.tan(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.tan(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.tan(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.tan(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.tan(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.tan(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.tan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.tan(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.tan(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float x;
                    float y;
                    float tf;
                    float ox;
                    float oy;
                    x = (float) (2. * ix);
                    y = (float) (2. * iy);
                    tf = (float) (1. / (Math.cos(x) + Math.cosh(y)));
                    ox = (float) (tf * Math.sin(x));
                    oy = (float) (tf * Math.sinh(y));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float x;
                    float y;
                    float tf;
                    float ox;
                    float oy;
                    x = (float) (2. * ix);
                    y = (float) (2. * iy);
                    tf = (float) (1. / (Math.cos(x) + Math.cosh(y)));
                    ox = (float) (tf * Math.sin(x));
                    oy = (float) (tf * Math.sinh(y));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double x;
                    double y;
                    double tf;
                    double ox;
                    double oy;
                    x = (2. * ix);
                    y = (2. * iy);
                    tf = (1. / (Math.cos(x) + Math.cosh(y)));
                    ox = (tf * Math.sin(x));
                    oy = (tf * Math.sinh(y));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double x;
                    double y;
                    double tf;
                    double ox;
                    double oy;
                    x = (2. * ix);
                    y = (2. * iy);
                    tf = (1. / (Math.cos(x) + Math.cosh(y)));
                    ox = (tf * Math.sin(x));
                    oy = (tf * Math.sinh(y));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "tan supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "tan");
        return result;
    }

    /**
     * arcsin - evaluate the inverse sine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arcsin(final Object a) {
        return arcsin(a, null);
    }

    /**
     * arcsin - evaluate the inverse sine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arcsin(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.asin(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.asin(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.asin(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.asin(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.asin(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.asin(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.asin(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.asin(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.asin(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.asin(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.asin(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.asin(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.asin(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.asin(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.asin(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.asin(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.asin(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.asin(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.asin(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.asin(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.asin(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.asin(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.asin(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.asin(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.asin(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.asin(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.asin(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.asin(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.asin(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.asin(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.asin(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.asin(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.asin(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.asin(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.asin(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.asin(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.asin(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).asin();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).asin();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).asin();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).asin();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arcsin supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arcsin");
        return result;
    }

    /**
     * arccos - evaluate the inverse cosine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arccos(final Object a) {
        return arccos(a, null);
    }

    /**
     * arccos - evaluate the inverse cosine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arccos(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.acos(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.acos(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.acos(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.acos(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.acos(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.acos(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.acos(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.acos(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.acos(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.acos(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.acos(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.acos(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.acos(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.acos(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.acos(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.acos(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.acos(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.acos(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.acos(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.acos(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.acos(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.acos(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.acos(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.acos(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.acos(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.acos(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.acos(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.acos(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.acos(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.acos(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.acos(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.acos(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.acos(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.acos(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.acos(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.acos(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.acos(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).acos();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).acos();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).acos();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).acos();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arccos supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arccos");
        return result;
    }

    /**
     * arctan - evaluate the inverse tangent function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arctan(final Object a) {
        return arctan(a, null);
    }

    /**
     * arctan - evaluate the inverse tangent function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arctan(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.atan(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.atan(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.atan(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.atan(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.atan(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.atan(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.atan(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.atan(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.atan(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.atan(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.atan(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.atan(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.atan(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.atan(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.atan(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.atan(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.atan(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.atan(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.atan(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.atan(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.atan(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.atan(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.atan(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.atan(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.atan(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.atan(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.atan(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.atan(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.atan(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.atan(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.atan(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.atan(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.atan(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.atan(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.atan(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.atan(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.atan(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).atan();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).atan();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).atan();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).atan();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arctan supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arctan");
        return result;
    }

    /**
     * sinh - evaluate the hyperbolic sine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset sinh(final Object a) {
        return sinh(a, null);
    }

    /**
     * sinh - evaluate the hyperbolic sine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset sinh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.sinh(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.sinh(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.sinh(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.sinh(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.sinh(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.sinh(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.sinh(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.sinh(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sinh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sinh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sinh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sinh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sinh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sinh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sinh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sinh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sinh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sinh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sinh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sinh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sinh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sinh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sinh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sinh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.sinh(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.sinh(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.sinh(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.sinh(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sinh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sinh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sinh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sinh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sinh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sinh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sinh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sinh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sinh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.sinh(ix) * Math.cos(iy));
                    oy = (float) (Math.cosh(ix) * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.sinh(ix) * Math.cos(iy));
                    oy = (float) (Math.cosh(ix) * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.sinh(ix) * Math.cos(iy));
                    oy = (Math.cosh(ix) * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.sinh(ix) * Math.cos(iy));
                    oy = (Math.cosh(ix) * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "sinh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "sinh");
        return result;
    }

    /**
     * cosh - evaluate the hyperbolic cosine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset cosh(final Object a) {
        return cosh(a, null);
    }

    /**
     * cosh - evaluate the hyperbolic cosine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset cosh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.cosh(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.cosh(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.cosh(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.cosh(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.cosh(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.cosh(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.cosh(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.cosh(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cosh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cosh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cosh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cosh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cosh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cosh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cosh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cosh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cosh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cosh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cosh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cosh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cosh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cosh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cosh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cosh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.cosh(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.cosh(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.cosh(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.cosh(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cosh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cosh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cosh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cosh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cosh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cosh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cosh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cosh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cosh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.cosh(ix) * Math.cos(iy));
                    oy = (float) (Math.sinh(ix) * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.cosh(ix) * Math.cos(iy));
                    oy = (float) (Math.sinh(ix) * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.cosh(ix) * Math.cos(iy));
                    oy = (Math.sinh(ix) * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.cosh(ix) * Math.cos(iy));
                    oy = (Math.sinh(ix) * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "cosh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "cosh");
        return result;
    }

    /**
     * tanh - evaluate the tangent hyperbolic function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset tanh(final Object a) {
        return tanh(a, null);
    }

    /**
     * tanh - evaluate the tangent hyperbolic function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset tanh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.tanh(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.tanh(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.tanh(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.tanh(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.tanh(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.tanh(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.tanh(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.tanh(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.tanh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.tanh(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.tanh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.tanh(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.tanh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.tanh(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.tanh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.tanh(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.tanh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.tanh(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.tanh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.tanh(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.tanh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.tanh(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.tanh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.tanh(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.tanh(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.tanh(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.tanh(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.tanh(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.tanh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.tanh(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.tanh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.tanh(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.tanh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.tanh(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.tanh(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.tanh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.tanh(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float tx;
                    float ty;
                    float tf;
                    float ox;
                    float oy;
                    tx = (float) (2. * ix);
                    ty = (float) (2. * iy);
                    tf = (float) (1. / (Math.cos(tx) + Math.cosh(ty)));
                    ox = (float) (tf * Math.sinh(tx));
                    oy = (float) (tf * Math.sin(ty));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float tx;
                    float ty;
                    float tf;
                    float ox;
                    float oy;
                    tx = (float) (2. * ix);
                    ty = (float) (2. * iy);
                    tf = (float) (1. / (Math.cos(tx) + Math.cosh(ty)));
                    ox = (float) (tf * Math.sinh(tx));
                    oy = (float) (tf * Math.sin(ty));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double tx;
                    double ty;
                    double tf;
                    double ox;
                    double oy;
                    tx = (2. * ix);
                    ty = (2. * iy);
                    tf = (1. / (Math.cos(tx) + Math.cosh(ty)));
                    ox = (tf * Math.sinh(tx));
                    oy = (tf * Math.sin(ty));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double tx;
                    double ty;
                    double tf;
                    double ox;
                    double oy;
                    tx = (2. * ix);
                    ty = (2. * iy);
                    tf = (1. / (Math.cos(tx) + Math.cosh(ty)));
                    ox = (tf * Math.sinh(tx));
                    oy = (tf * Math.sin(ty));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "tanh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "tanh");
        return result;
    }

    /**
     * arcsinh - evaluate the inverse hyperbolic sine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arcsinh(final Object a) {
        return arcsinh(a, null);
    }

    /**
     * arcsinh - evaluate the inverse hyperbolic sine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arcsinh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix + Math.sqrt(ix * ix + 1)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).asin();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).asin();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).asin();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).asin();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arcsinh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arcsinh");
        return result;
    }

    /**
     * arccosh - evaluate the inverse hyperbolic cosine function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arccosh(final Object a) {
        return arccosh(a, null);
    }

    /**
     * arccosh - evaluate the inverse hyperbolic cosine function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arccosh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix + Math.sqrt(ix * ix - 1)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).acos();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).acos();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).acos();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).acos();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arccosh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arccosh");
        return result;
    }

    /**
     * arctanh - evaluate the inverse hyperbolic tangent function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset arctanh(final Object a) {
        return arctanh(a, null);
    }

    /**
     * arctanh - evaluate the inverse hyperbolic tangent function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset arctanh(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(0.5 * Math.log((1 + ix) / (1 - ix)));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (0.5 * Math.log((1 + ix) / (1 - ix)));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (0.5 * Math.log((1 + ix) / (1 - ix)));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).atan();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(-iy, ix).atan();
                    ox = (float) (tz.getImaginary());
                    oy = (float) (-tz.getReal());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).atan();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(-iy, ix).atan();
                    ox = (tz.getImaginary());
                    oy = (-tz.getReal());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "arctanh supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "arctanh");
        return result;
    }

    /**
     * log - evaluate the logarithm function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset log(final Object a) {
        return log(a, null);
    }

    /**
     * log - evaluate the logarithm function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset log(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.log(Math.hypot(ix, iy)));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.log(Math.hypot(ix, iy)));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.log(Math.hypot(ix, iy)));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.log(Math.hypot(ix, iy)));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "log supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "log");
        return result;
    }

    /**
     * log2 - evaluate the logarithm function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset log2(final Object a) {
        return log2(a, null);
    }

    /**
     * log2 - evaluate the logarithm function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset log2(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log(ix) / Math.log(2.));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log(ix) / Math.log(2.));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log(ix) / Math.log(2.));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log(ix) / Math.log(2.));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log(ix) / Math.log(2.));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log(ix) / Math.log(2.));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log(ix) / Math.log(2.));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix) / Math.log(2.));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix) / Math.log(2.));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix) / Math.log(2.));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log(ix) / Math.log(2.));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix) / Math.log(2.));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix) / Math.log(2.));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix) / Math.log(2.));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log(ix) / Math.log(2.));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix) / Math.log(2.));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix) / Math.log(2.));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix) / Math.log(2.));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log(ix) / Math.log(2.));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log(ix) / Math.log(2.));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log(ix) / Math.log(2.));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log(ix) / Math.log(2.));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log(ix) / Math.log(2.));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix) / Math.log(2.));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix) / Math.log(2.));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix) / Math.log(2.));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log(ix) / Math.log(2.));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix) / Math.log(2.));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix) / Math.log(2.));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log(ix) / Math.log(2.));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix) / Math.log(2.));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log(ix) / Math.log(2.));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.log(Math.hypot(ix, iy)) / Math.log(2.));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.log(Math.hypot(ix, iy)) / Math.log(2.));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.log(Math.hypot(ix, iy)) / Math.log(2.));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.log(Math.hypot(ix, iy)) / Math.log(2.));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "log2 supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "log2");
        return result;
    }

    /**
     * log10 - evaluate the logarithm function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset log10(final Object a) {
        return log10(a, null);
    }

    /**
     * log10 - evaluate the logarithm function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset log10(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log10(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log10(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log10(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log10(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log10(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log10(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log10(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log10(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log10(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log10(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log10(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log10(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log10(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log10(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log10(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log10(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log10(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log10(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log10(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log10(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log10(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log10(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log10(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log10(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log10(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log10(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log10(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log10(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log10(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log10(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log10(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log10(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log10(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log10(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log10(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log10(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log10(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.log10(Math.hypot(ix, iy)));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.log10(Math.hypot(ix, iy)));
                    oy = (float) (Math.atan2(iy, ix));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.log10(Math.hypot(ix, iy)));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.log10(Math.hypot(ix, iy)));
                    oy = (Math.atan2(iy, ix));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "log10 supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "log10");
        return result;
    }

    /**
     * log1p - evaluate the logarithm function of 1 plus on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset log1p(final Object a) {
        return log1p(a, null);
    }

    /**
     * log1p - evaluate the logarithm function of 1 plus on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset log1p(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.log1p(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.log1p(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.log1p(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.log1p(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.log1p(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.log1p(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.log1p(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.log1p(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log1p(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log1p(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log1p(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.log1p(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log1p(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log1p(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log1p(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.log1p(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log1p(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log1p(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log1p(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.log1p(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log1p(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log1p(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log1p(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.log1p(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.log1p(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.log1p(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.log1p(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.log1p(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log1p(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log1p(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log1p(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.log1p(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log1p(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log1p(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.log1p(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log1p(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.log1p(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (0.5 * Math.log1p(ix * ix + 2. * ix + iy * iy));
                    oy = (float) (Math.atan2(iy, ix + 1));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (0.5 * Math.log1p(ix * ix + 2. * ix + iy * iy));
                    oy = (float) (Math.atan2(iy, ix + 1));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (0.5 * Math.log1p(ix * ix + 2. * ix + iy * iy));
                    oy = (Math.atan2(iy, ix + 1));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (0.5 * Math.log1p(ix * ix + 2. * ix + iy * iy));
                    oy = (Math.atan2(iy, ix + 1));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "log1p supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "log1p");
        return result;
    }

    /**
     * exp - evaluate the exponential function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset exp(final Object a) {
        return exp(a, null);
    }

    /**
     * exp - evaluate the exponential function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset exp(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.exp(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.exp(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.exp(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.exp(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.exp(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.exp(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.exp(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.exp(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.exp(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.exp(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.exp(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.exp(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.exp(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.exp(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.exp(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.exp(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.exp(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.exp(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.exp(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.exp(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.exp(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.exp(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.exp(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.exp(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.exp(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.exp(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.exp(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.exp(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.exp(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.exp(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.exp(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.exp(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.exp(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.exp(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.exp(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.exp(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.exp(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float tf;
                    float ox;
                    float oy;
                    tf = (float) (Math.exp(ix));
                    ox = (float) (tf * Math.cos(iy));
                    oy = (float) (tf * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float tf;
                    float ox;
                    float oy;
                    tf = (float) (Math.exp(ix));
                    ox = (float) (tf * Math.cos(iy));
                    oy = (float) (tf * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double tf;
                    double ox;
                    double oy;
                    tf = (Math.exp(ix));
                    ox = (tf * Math.cos(iy));
                    oy = (tf * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double tf;
                    double ox;
                    double oy;
                    tf = (Math.exp(ix));
                    ox = (tf * Math.cos(iy));
                    oy = (tf * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "exp supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "exp");
        return result;
    }

    /**
     * expm1 - evaluate the exponential function - 1 on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset expm1(final Object a) {
        return expm1(a, null);
    }

    /**
     * expm1 - evaluate the exponential function - 1 on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset expm1(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.expm1(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.expm1(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.expm1(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.expm1(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.expm1(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.expm1(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.expm1(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.expm1(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.expm1(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.expm1(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.expm1(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.expm1(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.expm1(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.expm1(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.expm1(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.expm1(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.expm1(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.expm1(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.expm1(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.expm1(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.expm1(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.expm1(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.expm1(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.expm1(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.expm1(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.expm1(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.expm1(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.expm1(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.expm1(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.expm1(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.expm1(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.expm1(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.expm1(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.expm1(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.expm1(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.expm1(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.expm1(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float tf;
                    float ox;
                    float oy;
                    tf = (float) (Math.expm1(ix));
                    ox = (float) (tf * Math.cos(iy));
                    oy = (float) (tf * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float tf;
                    float ox;
                    float oy;
                    tf = (float) (Math.expm1(ix));
                    ox = (float) (tf * Math.cos(iy));
                    oy = (float) (tf * Math.sin(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double tf;
                    double ox;
                    double oy;
                    tf = (Math.expm1(ix));
                    ox = (tf * Math.cos(iy));
                    oy = (tf * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double tf;
                    double ox;
                    double oy;
                    tf = (Math.expm1(ix));
                    ox = (tf * Math.cos(iy));
                    oy = (tf * Math.sin(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "expm1 supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "expm1");
        return result;
    }

    /**
     * sqrt - evaluate the square root function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset sqrt(final Object a) {
        return sqrt(a, null);
    }

    /**
     * sqrt - evaluate the square root function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset sqrt(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.sqrt(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.sqrt(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.sqrt(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.sqrt(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.sqrt(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.sqrt(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.sqrt(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.sqrt(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sqrt(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sqrt(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sqrt(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.sqrt(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sqrt(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sqrt(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sqrt(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.sqrt(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sqrt(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sqrt(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sqrt(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.sqrt(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sqrt(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sqrt(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sqrt(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.sqrt(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.sqrt(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.sqrt(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.sqrt(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.sqrt(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sqrt(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sqrt(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sqrt(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.sqrt(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sqrt(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sqrt(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.sqrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sqrt(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.sqrt(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).sqrt();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).sqrt();
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).sqrt();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).sqrt();
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "sqrt supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "sqrt");
        return result;
    }

    /**
     * cbrt - evaluate the cube root function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset cbrt(final Object a) {
        return cbrt(a, null);
    }

    /**
     * cbrt - evaluate the cube root function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset cbrt(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.cbrt(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.cbrt(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.cbrt(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.cbrt(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.cbrt(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.cbrt(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.cbrt(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.cbrt(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cbrt(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cbrt(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cbrt(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.cbrt(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cbrt(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cbrt(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cbrt(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.cbrt(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cbrt(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cbrt(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cbrt(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.cbrt(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cbrt(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cbrt(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cbrt(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.cbrt(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.cbrt(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.cbrt(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.cbrt(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.cbrt(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cbrt(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cbrt(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cbrt(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.cbrt(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cbrt(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cbrt(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.cbrt(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cbrt(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.cbrt(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).pow(new Complex(1. / 3., 0));
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    float ox;
                    float oy;
                    tz = new Complex(ix, iy).pow(new Complex(1. / 3., 0));
                    ox = (float) (tz.getReal());
                    oy = (float) (tz.getImaginary());
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).pow(new Complex(1. / 3., 0));
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    Complex tz;
                    double ox;
                    double oy;
                    tz = new Complex(ix, iy).pow(new Complex(1. / 3., 0));
                    ox = (tz.getReal());
                    oy = (tz.getImaginary());
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "cbrt supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "cbrt");
        return result;
    }

    /**
     * square - square each element
     * @param a
     * @return dataset
     */
    public static Dataset square(final Object a) {
        return square(a, null);
    }

    /**
     * square - square each element
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset square(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix * ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix * ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix * ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix * ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix * ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix * ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix * ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix * ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix * ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix * ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix * ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix * ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix * ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix * ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix * ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix * ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix * ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix * ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix * ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix * ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix * ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix * ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix * ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix * ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix * ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (ix * ix);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (ix * ix);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (ix * ix);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (ix * ix);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (ix * ix);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (ix * ix);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (ix * ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (ix * ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (ix * ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (ix * ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (ix * ix);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (ix * ix);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (ix * ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (ix * ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (ix * ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (ix * ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (ix * ix - iy * iy);
                    oy = (float) (2. * ix * iy);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (ix * ix - iy * iy);
                    oy = (float) (2. * ix * iy);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (ix * ix - iy * iy);
                    oy = (2. * ix * iy);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (ix * ix - iy * iy);
                    oy = (2. * ix * iy);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "square supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "square");
        return result;
    }

    /**
     * floor - evaluate the floor function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset floor(final Object a) {
        return floor(a, null);
    }

    /**
     * floor - evaluate the floor function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset floor(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.floor(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.floor(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.floor(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.floor(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.floor(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.floor(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.floor(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.floor(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.floor(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.floor(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.floor(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.floor(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.floor(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.floor(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.floor(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.floor(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.floor(ix));
                    oy = (float) (Math.floor(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.floor(ix));
                    oy = (float) (Math.floor(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.floor(ix));
                    oy = (Math.floor(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.floor(ix));
                    oy = (Math.floor(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "floor supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "floor");
        return result;
    }

    /**
     * ceil - evaluate the ceiling function on each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset ceil(final Object a) {
        return ceil(a, null);
    }

    /**
     * ceil - evaluate the ceiling function on each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset ceil(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.ceil(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.ceil(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.ceil(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.ceil(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.ceil(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.ceil(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.ceil(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.ceil(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.ceil(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.ceil(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.ceil(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.ceil(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.ceil(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.ceil(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.ceil(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.ceil(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.ceil(ix));
                    oy = (float) (Math.ceil(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.ceil(ix));
                    oy = (float) (Math.ceil(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.ceil(ix));
                    oy = (Math.ceil(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.ceil(ix));
                    oy = (Math.ceil(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "ceil supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "ceil");
        return result;
    }

    /**
     * rint - round each element of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset rint(final Object a) {
        return rint(a, null);
    }

    /**
     * rint - round each element of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset rint(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.rint(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.rint(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.rint(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.rint(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.rint(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.rint(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.rint(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.rint(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.rint(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.rint(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.rint(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.rint(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.rint(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.rint(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.rint(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.rint(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.rint(ix));
                    oy = (float) (Math.rint(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.rint(ix));
                    oy = (float) (Math.rint(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.rint(ix));
                    oy = (Math.rint(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.rint(ix));
                    oy = (Math.rint(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "rint supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "rint");
        return result;
    }

    /**
     * truncate - truncate each element to integers of the dataset
     * @param a
     * @return dataset
     */
    public static Dataset truncate(final Object a) {
        return truncate(a, null);
    }

    /**
     * truncate - truncate each element to integers of the dataset
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset truncate(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (toLong(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (toLong(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (toLong(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (toLong(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (toLong(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (toLong(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (toLong(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (toLong(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (toLong(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (toLong(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (toLong(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (toLong(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (toLong(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (toLong(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (toLong(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (toLong(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (toLong(ix));
                    oy = (float) (toLong(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (toLong(ix));
                    oy = (float) (toLong(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (toLong(ix));
                    oy = (toLong(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (toLong(ix));
                    oy = (toLong(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "truncate supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "truncate");
        return result;
    }

    /**
     * toDegrees - convert to degrees
     * @param a
     * @return dataset
     */
    public static Dataset toDegrees(final Object a) {
        return toDegrees(a, null);
    }

    /**
     * toDegrees - convert to degrees
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset toDegrees(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.toDegrees(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.toDegrees(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.toDegrees(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.toDegrees(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.toDegrees(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.toDegrees(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.toDegrees(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.toDegrees(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.toDegrees(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.toDegrees(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.toDegrees(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.toDegrees(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.toDegrees(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.toDegrees(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.toDegrees(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.toDegrees(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.toDegrees(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.toDegrees(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.toDegrees(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.toDegrees(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.toDegrees(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.toDegrees(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.toDegrees(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.toDegrees(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.toDegrees(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.toDegrees(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.toDegrees(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.toDegrees(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.toDegrees(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.toDegrees(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.toDegrees(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.toDegrees(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.toDegrees(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.toDegrees(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.toDegrees(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.toDegrees(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.toDegrees(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.toDegrees(ix));
                    oy = (float) (Math.toDegrees(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.toDegrees(ix));
                    oy = (float) (Math.toDegrees(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.toDegrees(ix));
                    oy = (Math.toDegrees(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.toDegrees(ix));
                    oy = (Math.toDegrees(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "toDegrees supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "toDegrees");
        return result;
    }

    /**
     * toRadians - convert to radians
     * @param a
     * @return dataset
     */
    public static Dataset toRadians(final Object a) {
        return toRadians(a, null);
    }

    /**
     * toRadians - convert to radians
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset toRadians(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(Math.toRadians(ix));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(Math.toRadians(ix));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(Math.toRadians(ix));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(Math.toRadians(ix));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(Math.toRadians(ix));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(Math.toRadians(ix));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(Math.toRadians(ix));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(Math.toRadians(ix));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.toRadians(ix));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.toRadians(ix));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.toRadians(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(Math.toRadians(ix));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.toRadians(ix));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.toRadians(ix));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.toRadians(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(Math.toRadians(ix));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.toRadians(ix));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.toRadians(ix));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.toRadians(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(Math.toRadians(ix));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.toRadians(ix));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.toRadians(ix));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.toRadians(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(Math.toRadians(ix));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.toRadians(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.toRadians(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.toRadians(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.toRadians(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.toRadians(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.toRadians(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.toRadians(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.toRadians(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.toRadians(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.toRadians(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.toRadians(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.toRadians(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.toRadians(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.toRadians(ix));
                    oy = (float) (Math.toRadians(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.toRadians(ix));
                    oy = (float) (Math.toRadians(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.toRadians(ix));
                    oy = (Math.toRadians(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.toRadians(ix));
                    oy = (Math.toRadians(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "toRadians supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "toRadians");
        return result;
    }

    /**
     * signum - sign of each element
     * @param a
     * @return dataset
     */
    public static Dataset signum(final Object a) {
        return signum(a, null);
    }

    /**
     * signum - sign of each element
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset signum(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(ix > 0 ? 1 : (ix < 0 ? -1 : 0));
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (Math.signum(ix));
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (float) (Math.signum(ix));
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (Math.signum(ix));
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (Math.signum(ix));
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.signum(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.signum(ix));
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (Math.signum(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (float) (Math.signum(ix));
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.signum(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (Math.signum(ix));
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.signum(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.signum(ix));
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (Math.signum(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (Math.signum(ix));
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.signum(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (Math.signum(ix));
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (Math.signum(ix));
                    oy = (float) (Math.signum(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (Math.signum(ix));
                    oy = (float) (Math.signum(iy));
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (Math.signum(ix));
                    oy = (Math.signum(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (Math.signum(ix));
                    oy = (Math.signum(iy));
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "signum supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "signum");
        return result;
    }

    /**
     * negative - negative value of each element
     * @param a
     * @return dataset
     */
    public static Dataset negative(final Object a) {
        return negative(a, null);
    }

    /**
     * negative - negative value of each element
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @return dataset
     */
    public static Dataset negative(final Object a, final Dataset o) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    ox = (byte) toLong(-ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    ox = (byte) toLong(-ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    ox = (short) toLong(-ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    ox = (short) toLong(-ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    ox = toLong(-ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    ox = toLong(-ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    ox = (int) toLong(-ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    ox = (int) toLong(-ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(-ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(-ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        ox = (byte) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        ox = (byte) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(-ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            ox = (byte) toLong(-ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(-ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(-ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        ox = (short) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        ox = (short) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(-ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            ox = (short) toLong(-ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(-ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(-ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        ox = toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        ox = toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(-ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            ox = toLong(-ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(-ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(-ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        ox = (int) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        ox = (int) toLong(-ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(-ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            ox = (int) toLong(-ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    ox = (float) (-ix);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    ox = (-ix);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    ox = (-ix);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    ox = (-ix);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (-ix);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (-ix);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        ox = (float) (-ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        ox = (-ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            ox = (float) (-ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            ox = (-ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (-ix);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (-ix);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        ox = (-ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        ox = (-ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            ox = (-ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            ox = (-ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.COMPLEX64:
            final float[] oc64data = ((ComplexFloatDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    float oy;
                    ox = (float) (-ix);
                    oy = (float) (-iy);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    float ox;
                    float oy;
                    ox = (float) (-ix);
                    oy = (float) (-iy);
                    oc64data[it.oIndex] = ox;
                    oc64data[it.oIndex + 1] = oy;
                }
            }
            break;
        case Dataset.COMPLEX128:
            final double[] oc128data = ((ComplexDoubleDataset) result).getData();
            if (as == 1) {
                final double iy = 0;
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    double oy;
                    ox = (-ix);
                    oy = (-iy);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            } else {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    final double iy = da.getElementDoubleAbs(it.aIndex + 1);
                    double ox;
                    double oy;
                    ox = (-ix);
                    oy = (-iy);
                    oc128data[it.oIndex] = ox;
                    oc128data[it.oIndex + 1] = oy;
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "negative supports integer, compound integer, real, compound real, complex datasets only");
        }

        addFunctionName(result, "negative");
        return result;
    }

    /**
     * clip - clip elements to limits
     * @param a
     * @param pa
     * @param pb
     * @return dataset
     */
    public static Dataset clip(final Object a, final Object pa, final Object pb) {
        return clip(a, null, pa, pb);
    }

    /**
     * clip - clip elements to limits
     * @param a
     * @param o output can be null - in which case, a new dataset is created
     * @param pa
     * @param pb
     * @return dataset
     */
    public static Dataset clip(final Object a, final Dataset o, final Object pa, final Object pb) {
        final Dataset da = a instanceof Dataset ? (Dataset) a : DatasetFactory.createFromObject(a);
        final SingleInputBroadcastIterator it = new SingleInputBroadcastIterator(da, o, true);
        final Dataset result = it.getOutput();
        final int is = result.getElementsPerItem();
        final int as = da.getElementsPerItem();
        final int dt = result.getDType();
        final double pax = DTypeUtils.toReal(pa);
        final double pbx = DTypeUtils.toReal(pb);

        switch (dt) {
        case Dataset.INT8:
            final byte[] oi8data = ((ByteDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    byte ox;
                    if (ix < pax)
                        ox = (byte) toLong(pax);
                    else if (ix > pbx)
                        ox = (byte) toLong(pbx);
                    else
                        ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    byte ox;
                    if (ix < pax)
                        ox = (byte) toLong(pax);
                    else if (ix > pbx)
                        ox = (byte) toLong(pbx);
                    else
                        ox = (byte) toLong(ix);
                    oi8data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT16:
            final short[] oi16data = ((ShortDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    short ox;
                    if (ix < pax)
                        ox = (short) toLong(pax);
                    else if (ix > pbx)
                        ox = (short) toLong(pbx);
                    else
                        ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    short ox;
                    if (ix < pax)
                        ox = (short) toLong(pax);
                    else if (ix > pbx)
                        ox = (short) toLong(pbx);
                    else
                        ox = (short) toLong(ix);
                    oi16data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT64:
            final long[] oi64data = ((LongDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    long ox;
                    if (ix < pax)
                        ox = toLong(pax);
                    else if (ix > pbx)
                        ox = toLong(pbx);
                    else
                        ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    long ox;
                    if (ix < pax)
                        ox = toLong(pax);
                    else if (ix > pbx)
                        ox = toLong(pbx);
                    else
                        ox = toLong(ix);
                    oi64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.INT32:
            final int[] oi32data = ((IntegerDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    int ox;
                    if (ix < pax)
                        ox = (int) toLong(pax);
                    else if (ix > pbx)
                        ox = (int) toLong(pbx);
                    else
                        ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    int ox;
                    if (ix < pax)
                        ox = (int) toLong(pax);
                    else if (ix > pbx)
                        ox = (int) toLong(pbx);
                    else
                        ox = (int) toLong(ix);
                    oi32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYINT8:
            final byte[] oai8data = ((CompoundByteDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        if (ix < pax)
                            ox = (byte) toLong(pax);
                        else if (ix > pbx)
                            ox = (byte) toLong(pbx);
                        else
                            ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        if (ix < pax)
                            ox = (byte) toLong(pax);
                        else if (ix > pbx)
                            ox = (byte) toLong(pbx);
                        else
                            ox = (byte) toLong(ix);
                        oai8data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        byte ox;
                        if (ix < pax)
                            ox = (byte) toLong(pax);
                        else if (ix > pbx)
                            ox = (byte) toLong(pbx);
                        else
                            ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        byte ox;
                        if (ix < pax)
                            ox = (byte) toLong(pax);
                        else if (ix > pbx)
                            ox = (byte) toLong(pbx);
                        else
                            ox = (byte) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            byte ox;
                            if (ix < pax)
                                ox = (byte) toLong(pax);
                            else if (ix > pbx)
                                ox = (byte) toLong(pbx);
                            else
                                ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            byte ox;
                            if (ix < pax)
                                ox = (byte) toLong(pax);
                            else if (ix > pbx)
                                ox = (byte) toLong(pbx);
                            else
                                ox = (byte) toLong(ix);
                            oai8data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT16:
            final short[] oai16data = ((CompoundShortDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        if (ix < pax)
                            ox = (short) toLong(pax);
                        else if (ix > pbx)
                            ox = (short) toLong(pbx);
                        else
                            ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        if (ix < pax)
                            ox = (short) toLong(pax);
                        else if (ix > pbx)
                            ox = (short) toLong(pbx);
                        else
                            ox = (short) toLong(ix);
                        oai16data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        short ox;
                        if (ix < pax)
                            ox = (short) toLong(pax);
                        else if (ix > pbx)
                            ox = (short) toLong(pbx);
                        else
                            ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        short ox;
                        if (ix < pax)
                            ox = (short) toLong(pax);
                        else if (ix > pbx)
                            ox = (short) toLong(pbx);
                        else
                            ox = (short) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            short ox;
                            if (ix < pax)
                                ox = (short) toLong(pax);
                            else if (ix > pbx)
                                ox = (short) toLong(pbx);
                            else
                                ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            short ox;
                            if (ix < pax)
                                ox = (short) toLong(pax);
                            else if (ix > pbx)
                                ox = (short) toLong(pbx);
                            else
                                ox = (short) toLong(ix);
                            oai16data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT64:
            final long[] oai64data = ((CompoundLongDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        if (ix < pax)
                            ox = toLong(pax);
                        else if (ix > pbx)
                            ox = toLong(pbx);
                        else
                            ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        if (ix < pax)
                            ox = toLong(pax);
                        else if (ix > pbx)
                            ox = toLong(pbx);
                        else
                            ox = toLong(ix);
                        oai64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        long ox;
                        if (ix < pax)
                            ox = toLong(pax);
                        else if (ix > pbx)
                            ox = toLong(pbx);
                        else
                            ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        long ox;
                        if (ix < pax)
                            ox = toLong(pax);
                        else if (ix > pbx)
                            ox = toLong(pbx);
                        else
                            ox = toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            long ox;
                            if (ix < pax)
                                ox = toLong(pax);
                            else if (ix > pbx)
                                ox = toLong(pbx);
                            else
                                ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            long ox;
                            if (ix < pax)
                                ox = toLong(pax);
                            else if (ix > pbx)
                                ox = toLong(pbx);
                            else
                                ox = toLong(ix);
                            oai64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYINT32:
            final int[] oai32data = ((CompoundIntegerDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        if (ix < pax)
                            ox = (int) toLong(pax);
                        else if (ix > pbx)
                            ox = (int) toLong(pbx);
                        else
                            ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        if (ix < pax)
                            ox = (int) toLong(pax);
                        else if (ix > pbx)
                            ox = (int) toLong(pbx);
                        else
                            ox = (int) toLong(ix);
                        oai32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        int ox;
                        if (ix < pax)
                            ox = (int) toLong(pax);
                        else if (ix > pbx)
                            ox = (int) toLong(pbx);
                        else
                            ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        int ox;
                        if (ix < pax)
                            ox = (int) toLong(pax);
                        else if (ix > pbx)
                            ox = (int) toLong(pbx);
                        else
                            ox = (int) toLong(ix);
                        for (int j = 0; j < is; j++) {
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            int ox;
                            if (ix < pax)
                                ox = (int) toLong(pax);
                            else if (ix > pbx)
                                ox = (int) toLong(pbx);
                            else
                                ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            int ox;
                            if (ix < pax)
                                ox = (int) toLong(pax);
                            else if (ix > pbx)
                                ox = (int) toLong(pbx);
                            else
                                ox = (int) toLong(ix);
                            oai32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.FLOAT32:
            final float[] of32data = ((FloatDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    float ox;
                    if (Double.isNaN(ix))
                        ox = (float) ((pax + pbx) / 2.);
                    else if (ix < pax)
                        ox = (float) (pax);
                    else if (ix > pbx)
                        ox = (float) (pbx);
                    else
                        ox = (float) (ix);
                    of32data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    float ox;
                    if (Double.isNaN(ix))
                        ox = (float) ((pax + pbx) / 2.);
                    else if (ix < pax)
                        ox = (float) (pax);
                    else if (ix > pbx)
                        ox = (float) (pbx);
                    else
                        ox = (ix);
                    of32data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.FLOAT64:
            final double[] of64data = ((DoubleDataset) result).getData();
            if (it.isOutputDouble()) {
                while (it.hasNext()) {
                    final double ix = it.aDouble;
                    double ox;
                    if (Double.isNaN(ix))
                        ox = ((pax + pbx) / 2.);
                    else if (ix < pax)
                        ox = (pax);
                    else if (ix > pbx)
                        ox = (pbx);
                    else
                        ox = (ix);
                    of64data[it.oIndex] = ox;
                }
            } else {
                while (it.hasNext()) {
                    final long ix = it.aLong;
                    double ox;
                    if (Double.isNaN(ix))
                        ox = ((pax + pbx) / 2.);
                    else if (ix < pax)
                        ox = (pax);
                    else if (ix > pbx)
                        ox = (pbx);
                    else
                        ox = (ix);
                    of64data[it.oIndex] = ox;
                }
            }
            break;
        case Dataset.ARRAYFLOAT32:
            final float[] oaf32data = ((CompoundFloatDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        if (Double.isNaN(ix))
                            ox = (float) ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (float) (pax);
                        else if (ix > pbx)
                            ox = (float) (pbx);
                        else
                            ox = (float) (ix);
                        oaf32data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        if (Double.isNaN(ix))
                            ox = (float) ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (float) (pax);
                        else if (ix > pbx)
                            ox = (float) (pbx);
                        else
                            ox = (ix);
                        oaf32data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        float ox;
                        if (Double.isNaN(ix))
                            ox = (float) ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (float) (pax);
                        else if (ix > pbx)
                            ox = (float) (pbx);
                        else
                            ox = (float) (ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        float ox;
                        if (Double.isNaN(ix))
                            ox = (float) ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (float) (pax);
                        else if (ix > pbx)
                            ox = (float) (pbx);
                        else
                            ox = (ix);
                        for (int j = 0; j < is; j++) {
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            float ox;
                            if (Double.isNaN(ix))
                                ox = (float) ((pax + pbx) / 2.);
                            else if (ix < pax)
                                ox = (float) (pax);
                            else if (ix > pbx)
                                ox = (float) (pbx);
                            else
                                ox = (float) (ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            float ox;
                            if (Double.isNaN(ix))
                                ox = (float) ((pax + pbx) / 2.);
                            else if (ix < pax)
                                ox = (float) (pax);
                            else if (ix > pbx)
                                ox = (float) (pbx);
                            else
                                ox = (ix);
                            oaf32data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        case Dataset.ARRAYFLOAT64:
            final double[] oaf64data = ((CompoundDoubleDataset) result).getData();
            if (is == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        if (Double.isNaN(ix))
                            ox = ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (pax);
                        else if (ix > pbx)
                            ox = (pbx);
                        else
                            ox = (ix);
                        oaf64data[it.oIndex] = ox;
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        if (Double.isNaN(ix))
                            ox = ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (pax);
                        else if (ix > pbx)
                            ox = (pbx);
                        else
                            ox = (ix);
                        oaf64data[it.oIndex] = ox;
                    }
                }
            } else if (as == 1) {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        final double ix = it.aDouble;
                        double ox;
                        if (Double.isNaN(ix))
                            ox = ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (pax);
                        else if (ix > pbx)
                            ox = (pbx);
                        else
                            ox = (ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        final long ix = it.aLong;
                        double ox;
                        if (Double.isNaN(ix))
                            ox = ((pax + pbx) / 2.);
                        else if (ix < pax)
                            ox = (pax);
                        else if (ix > pbx)
                            ox = (pbx);
                        else
                            ox = (ix);
                        for (int j = 0; j < is; j++) {
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            } else {
                if (it.isOutputDouble()) {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final double ix = da.getElementDoubleAbs(it.aIndex + j);
                            double ox;
                            if (Double.isNaN(ix))
                                ox = ((pax + pbx) / 2.);
                            else if (ix < pax)
                                ox = (pax);
                            else if (ix > pbx)
                                ox = (pbx);
                            else
                                ox = (ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                } else {
                    while (it.hasNext()) {
                        for (int j = 0; j < is; j++) {
                            final long ix = da.getElementLongAbs(it.aIndex + j);
                            double ox;
                            if (Double.isNaN(ix))
                                ox = ((pax + pbx) / 2.);
                            else if (ix < pax)
                                ox = (pax);
                            else if (ix > pbx)
                                ox = (pbx);
                            else
                                ox = (ix);
                            oaf64data[it.oIndex + j] = ox;
                        }
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                    "clip supports integer, compound integer, real, compound real datasets only");
        }

        addFunctionName(result, "clip");
        return result;
    }

    // End of generated code
}