@Override
    public Pair<DataBuffer, long[]> createShapeInformation(long[] shape, char order) {
        long[] stride = Nd4j.getStrides(shape, order);

        // this won't be view, so ews is 1
        int ews = 1;

        return createShapeInformation(shape, stride, 0, ews, order);
    }

@
Override
public
Pair
<
DataBuffer
,
long
[
]
>
createShapeInformation
(
long
[
]
shape
,
char
order
)
{
long
[
]
stride
=
Nd4j
.
getStrides
(
shape
,
order
)
;
// this won't be view, so ews is 1
int
ews
=
1
;
return
createShapeInformation
(
shape
,
stride
,
0
,
ews
,
order
)
;
}

This method creates shapeInformation buffer, based on shape & order being passed in

@param shape
@param order
@return

This method creates shapeInformation buffer based on shape & order being passed in


public static boolean isVector(DataBuffer shapeInfo) {
        int rank = Shape.rank(shapeInfo);
        if (rank > 2 || rank < 1)
            return false;
        else {
            int len = Shape.length(shapeInfo);
            DataBuffer shape = Shape.shapeOf(shapeInfo);
            return shape.getInt(0) == len || shape.getInt(1) == len;
        }
    }

public static boolean isVector ( DataBuffer shapeInfo ) { int rank = Shape . rank ( shapeInfo ) ; if ( rank > 2 || rank < 1 ) return false ; else { int len = Shape . length ( shapeInfo ) ; DataBuffer shape = Shape . shapeOf ( shapeInfo ) ; return shape . getInt ( 0 ) == len || shape . getInt ( 1 ) == len ; } }

Returns whether the given shape is a vector

@param shapeInfo the shapeinfo to test
@return whether the given shape is a vector


public static char getOrder(INDArray arr) {
        return getOrder(arr.shape(), arr.stride(), arr.elementStride());
    }

public static char getOrder ( INDArray arr ) { return getOrder ( arr . shape ( ) , arr . stride ( ) , arr . elementStride ( ) ) ; }

Infer the order for the ndarray based on the
array's strides
@param arr the array to get the
ordering for
@return the ordering for the given array

Infer the order for the ndarray based on the array s strides


public static long offsetFor(INDArray arr, int[] indexes) {
        ShapeOffsetResolution resolution = new ShapeOffsetResolution(arr);
        resolution.exec(Shape.toIndexes(indexes));
        return resolution.getOffset();
    }

public static long offsetFor ( INDArray arr , int [ ] indexes ) { ShapeOffsetResolution resolution = new ShapeOffsetResolution ( arr ) ; resolution . exec ( Shape . toIndexes ( indexes ) ) ; return resolution . getOffset ( ) ; }

Compute the offset for the given array
given the indices
@param arr the array to compute the offset for
@param indexes the indexes along each dimension to create the offset for
@return the offset for the given array and indexes


public static INDArrayIndex[] toIndexes(int[] indices) {
        INDArrayIndex[] ret = new INDArrayIndex[indices.length];
        for (int i = 0; i < ret.length; i++)
            ret[i] = new NDArrayIndex(indices[i]);
        return ret;
    }

public static INDArrayIndex [ ] toIndexes ( int [ ] indices ) { INDArrayIndex [ ] ret = new INDArrayIndex [ indices . length ] ; for ( int i = 0 ; i < ret . length ; i ++ ) ret [ i ] = new NDArrayIndex ( indices [ i ] ) ; return ret ; }

Convert the given int indexes
to nd array indexes
@param indices the indices to convert
@return the converted indexes


protected short getShort(long i) {
        if (dataType() != Type.HALF)
            throw new UnsupportedOperationException("getShort() is supported for Half-precision buffers only");

        return fromFloat(((HalfIndexer) indexer).get(offset() + i));
    }


@Override
    public DataBuffer reallocate(long length) {

        Pointer oldPointer = pointer;
        if (isAttached()) {
            long capacity = length * getElementSize();
            switch (dataType()) {
                case DOUBLE:
                    pointer = getParentWorkspace().alloc(capacity, Type.DOUBLE, false).asDoublePointer();
                    indexer = DoubleIndexer.create((DoublePointer) pointer);
                    break;
                case FLOAT:
                    pointer = getParentWorkspace().alloc(capacity, Type.FLOAT, false).asFloatPointer();
                    indexer = FloatIndexer.create((FloatPointer) pointer);
                    break;
                case INT:
                    pointer = getParentWorkspace().alloc(capacity, Type.INT, false).asIntPointer();
                    indexer = IntIndexer.create((IntPointer) pointer);

                    break;
            }

            workspaceGenerationId = getParentWorkspace().getGenerationId();
        } else {
            switch (dataType()) {
                case INT:
                    pointer = new IntPointer(length);
                    indexer = IntIndexer.create((IntPointer) pointer);
                    break;
                case DOUBLE:
                    pointer = new DoublePointer(length);
                    indexer = DoubleIndexer.create((DoublePointer) pointer);
                    break;
                case FLOAT:
                    pointer = new FloatPointer(length);
                    indexer = FloatIndexer.create((FloatPointer) pointer);
                    break;
            }
        }

        Pointer.memcpy(pointer, oldPointer, this.length() * getElementSize());
        //this.underlyingLength = length;
        return this;
    }

@
Override
public
DataBuffer
reallocate
(
long
length
)
{
Pointer
oldPointer
=
pointer
;
if
(
isAttached
(
)
)
{
long
capacity
=
length
*
getElementSize
(
)
;
switch
(
dataType
(
)
)
{
case
DOUBLE
:
pointer
=
getParentWorkspace
(
)
.
alloc
(
capacity
,
Type
.
DOUBLE
,
false
)
.
asDoublePointer
(
)
;
indexer
=
DoubleIndexer
.
create
(
(
DoublePointer
)
pointer
)
;
break
;
case
FLOAT
:
pointer
=
getParentWorkspace
(
)
.
alloc
(
capacity
,
Type
.
FLOAT
,
false
)
.
asFloatPointer
(
)
;
indexer
=
FloatIndexer
.
create
(
(
FloatPointer
)
pointer
)
;
break
;
case
INT
:
pointer
=
getParentWorkspace
(
)
.
alloc
(
capacity
,
Type
.
INT
,
false
)
.
asIntPointer
(
)
;
indexer
=
IntIndexer
.
create
(
(
IntPointer
)
pointer
)
;
break
;
}
workspaceGenerationId
=
getParentWorkspace
(
)
.
getGenerationId
(
)
;
}
else
{
switch
(
dataType
(
)
)
{
case
INT
:
pointer
=
new
IntPointer
(
length
)
;
indexer
=
IntIndexer
.
create
(
(
IntPointer
)
pointer
)
;
break
;
case
DOUBLE
:
pointer
=
new
DoublePointer
(
length
)
;
indexer
=
DoubleIndexer
.
create
(
(
DoublePointer
)
pointer
)
;
break
;
case
FLOAT
:
pointer
=
new
FloatPointer
(
length
)
;
indexer
=
FloatIndexer
.
create
(
(
FloatPointer
)
pointer
)
;
break
;
}
}
Pointer
.
memcpy
(
pointer
,
oldPointer
,
this
.
length
(
)
*
getElementSize
(
)
)
;
//this.underlyingLength = length;
return
this
;
}

Reallocate the native memory of the buffer
@param length the new length of the buffer
@return this databuffer


public static void copyAtStride(int n, BufferType bufferType, ByteBuffer from, int fromOffset, int fromStride,
                    ByteBuffer to, int toOffset, int toStride) {
        // TODO: implement shape copy for cases where stride == 1
        ByteBuffer fromView = from;
        ByteBuffer toView = to;
        fromView.order(ByteOrder.nativeOrder());
        toView.order(ByteOrder.nativeOrder());
        switch (bufferType) {
            case INT:
                IntBuffer fromInt = fromView.asIntBuffer();
                IntBuffer toInt = toView.asIntBuffer();
                for (int i = 0; i < n; i++) {
                    int put = fromInt.get(fromOffset + i * fromStride);
                    toInt.put(toOffset + i * toStride, put);
                }
                break;
            case FLOAT:
                FloatBuffer fromFloat = fromView.asFloatBuffer();
                FloatBuffer toFloat = toView.asFloatBuffer();
                for (int i = 0; i < n; i++) {
                    float put = fromFloat.get(fromOffset + i * fromStride);
                    toFloat.put(toOffset + i * toStride, put);
                }
                break;
            case DOUBLE:
                DoubleBuffer fromDouble = fromView.asDoubleBuffer();
                DoubleBuffer toDouble = toView.asDoubleBuffer();
                for (int i = 0; i < n; i++) {
                    toDouble.put(toOffset + i * toStride, fromDouble.get(fromOffset + i * fromStride));

                }
                break;
            default:
                throw new IllegalArgumentException("Only floats and double supported");

        }

    }

Copy from the given from buffer
to the to buffer at the specified
offsets and strides
@param n
@param bufferType
@param from the origin buffer
@param fromOffset the starting offset
@param fromStride the stride at which to copy from the origin
@param to the destination buffer
@param toOffset the starting point
@param toStride the to stride


@Override
    public DataBuffer getConstantBuffer(float[] array) {
        //   logger.info("getConstantBuffer(float[]) called");
        ArrayDescriptor descriptor = new ArrayDescriptor(array);

        Integer deviceId = AtomicAllocator.getInstance().getDeviceId();

        ensureMaps(deviceId);

        if (!buffersCache.get(deviceId).containsKey(descriptor)) {
            // we create new databuffer
                 //logger.info("Creating new constant buffer...");
            DataBuffer buffer = Nd4j.createBufferDetached(array);

            if (constantOffsets.get(deviceId).get() + (array.length * Nd4j.sizeOfDataType()) < MAX_CONSTANT_LENGTH) {
                buffer.setConstant(true);
                // now we move data to constant memory, and keep happy
                moveToConstantSpace(buffer);

                buffersCache.get(deviceId).put(descriptor, buffer);

                bytes.addAndGet(array.length * Nd4j.sizeOfDataType());
            }
            return buffer;
        } // else logger.info("Reusing constant buffer...");

        return buffersCache.get(deviceId).get(descriptor);
    }

This method returns DataBuffer with contant equal to input array.

PLEASE NOTE: This method assumes that you'll never ever change values within result DataBuffer

@param array
@return

This method returns DataBuffer with contant equal to input array .


public String kafkaUri() {
        return String.format(
                        "kafka://%s?topic=%s&groupId=%s&zookeeperHost=%s&zookeeperPort=%d&serializerClass=%s&keySerializerClass=%s",
                        kafkaBrokerList, topicName, groupId, zookeeperHost, zookeeperPort,
                        StringEncoder.class.getName(), StringEncoder.class.getName());
    }

Returns a kafka connection uri
@return a kafka connection uri
represented by this connection information


public static INDArray pow(INDArray ndArray, INDArray power, boolean dup) {
        INDArray result = (dup ? Nd4j.create(ndArray.shape(), ndArray.ordering()) : ndArray);
        return exec(new Pow(ndArray, power, result, ndArray.length(), 0));
    }

public static INDArray pow ( INDArray ndArray , INDArray power , boolean dup ) { INDArray result = ( dup ? Nd4j . create ( ndArray . shape ( ) , ndArray . ordering ( ) ) : ndArray ) ; return exec ( new Pow ( ndArray , power , result , ndArray . length ( ) , 0 ) ) ; }

Element-wise power function - x^y, performed element-wise

@param ndArray the ndarray to raise to the power of
@param power   the power to raise by
@param dup     if true:
@return the ndarray raised to this power

Element - wise power function - x^y performed element - wise


public static INDArray log(INDArray ndArray, double base, boolean duplicate) {
        return Nd4j.getExecutioner().exec(new LogX(duplicate ? ndArray.dup(ndArray.ordering()) : ndArray, base)).z();
    }

public static INDArray log ( INDArray ndArray , double base , boolean duplicate ) { return Nd4j . getExecutioner ( ) . exec ( new LogX ( duplicate ? ndArray . dup ( ndArray . ordering ( ) ) : ndArray , base ) ) . z ( ) ; }

Log on arbitrary base

@param ndArray
@param base
@return


public static INDArray max(INDArray ndArray, double k, boolean dup) {
        return exec(dup ? new ScalarMax(ndArray.dup(), k) : new ScalarMax(ndArray, k));
    }

public static INDArray max ( INDArray ndArray , double k , boolean dup ) { return exec ( dup ? new ScalarMax ( ndArray . dup ( ) , k ) : new ScalarMax ( ndArray , k ) ) ; }

Maximum function with a scalar

@param ndArray tbe ndarray
@param k
@param dup
@return


public static INDArray max(INDArray first, INDArray second, boolean dup) {
        if (dup) {
            first = first.dup();
        }
        return exec(new OldMax(second, first, first, first.length()));
    }

public static INDArray max ( INDArray first , INDArray second , boolean dup ) { if ( dup ) { first = first . dup ( ) ; } return exec ( new OldMax ( second , first , first , first . length ( ) ) ) ; }

Element wise maximum function between 2 INDArrays

@param first
@param second
@param dup
@return


public static INDArray min(INDArray ndArray, double k, boolean dup) {
        return exec(dup ? new ScalarMin(ndArray.dup(), k) : new ScalarMin(ndArray, k));
    }

public static INDArray min ( INDArray ndArray , double k , boolean dup ) { return exec ( dup ? new ScalarMin ( ndArray . dup ( ) , k ) : new ScalarMin ( ndArray , k ) ) ; }

Minimum function with a scalar

@param ndArray tbe ndarray
@param k
@param dup
@return


public static INDArray min(INDArray first, INDArray second, boolean dup) {
        if (dup) {
            first = first.dup();
        }
        return exec(new OldMin(second, first, first, first.length()));
    }

public static INDArray min ( INDArray first , INDArray second , boolean dup ) { if ( dup ) { first = first . dup ( ) ; } return exec ( new OldMin ( second , first , first , first . length ( ) ) ) ; }

Element wise minimum function between 2 INDArrays

@param first
@param second
@param dup
@return


public static INDArray stabilize(INDArray ndArray, double k, boolean dup) {
        return exec(dup ? new Stabilize(ndArray, ndArray.dup(), k) : new Stabilize(ndArray, k));
    }

public static INDArray stabilize ( INDArray ndArray , double k , boolean dup ) { return exec ( dup ? new Stabilize ( ndArray , ndArray . dup ( ) , k ) : new Stabilize ( ndArray , k ) ) ; }

Stabilize to be within a range of k

@param ndArray tbe ndarray
@param k
@param dup
@return


public static INDArray expm1(INDArray ndArray, boolean dup) {
        return exec(dup ? new Expm1(ndArray, ndArray.dup()) : new Expm1(ndArray));
    }

public static INDArray expm1 ( INDArray ndArray , boolean dup ) { return exec ( dup ? new Expm1 ( ndArray , ndArray . dup ( ) ) : new Expm1 ( ndArray ) ) ; }

Elementwise exponential - 1 function

@param ndArray
@param dup
@return


public static INDArray log1p(INDArray ndArray, boolean dup) {
        return exec(dup ? new Log1p(ndArray, ndArray.dup()) : new Log1p(ndArray));
    }

public static INDArray log1p ( INDArray ndArray , boolean dup ) { return exec ( dup ? new Log1p ( ndArray , ndArray . dup ( ) ) : new Log1p ( ndArray ) ) ; }

Log of x + 1 function

@param ndArray
@param dup
@return


public static INDArray[] prepareBounds(INDArray bounds,INDArray x) {
        return new INDArray[]  {Nd4j.valueArrayOf(x.shape(),bounds.getDouble(0)),
                Nd4j.valueArrayOf(x.shape(),bounds.getDouble(1))};
    }

public static INDArray [ ] prepareBounds ( INDArray bounds , INDArray x ) { return new INDArray [ ] { Nd4j . valueArrayOf ( x . shape ( ) , bounds . getDouble ( 0 ) ) , Nd4j . valueArrayOf ( x . shape ( ) , bounds . getDouble ( 1 ) ) } ; }

Prepare the boundaries for processing
@param bounds the bounds
@param x the input in to the approximation
@return the lower and upper bounds as an array of ndarrays
(in that order) of the same shape as x


public static INDArray[] adjustSchemeToBounds(INDArray x,INDArray h,int numSteps,INDArray lowerBound,INDArray upperBound) {
        INDArray oneSided = Nd4j.onesLike(h);
        if(and(lowerBound.eq(Double.NEGATIVE_INFINITY),upperBound.eq(Double.POSITIVE_INFINITY)).sumNumber().doubleValue() > 0) {
            return new INDArray[] {h,oneSided};
        }
        INDArray hTotal = h.mul(numSteps);
        INDArray hAdjusted = h.dup();
        INDArray lowerDist = x.sub(lowerBound);
        INDArray upperBound2 = upperBound.sub(x);

        INDArray central = and(greaterThanOrEqual(lowerDist,hTotal),greaterThanOrEqual(upperBound2,hTotal));
        INDArray forward = and(greaterThanOrEqual(upperBound,lowerDist),not(central));
        hAdjusted.put(forward,min(h.get(forward),upperBound2.get(forward).mul(0.5).divi(numSteps)));
        oneSided.put(forward,Nd4j.scalar(1.0));

        INDArray backward = and(upperBound2.lt(lowerBound),not(central));
        hAdjusted.put(backward,min(h.get(backward),lowerDist.get(backward).mul(0.5).divi(numSteps)));
        oneSided.put(backward,Nd4j.scalar(1.0));

        INDArray minDist = min(upperBound2,lowerDist).divi(numSteps);
        INDArray adjustedCentral = and(not(central),lessThanOrEqual(abs(hAdjusted),minDist));
        hAdjusted.put(adjustedCentral,minDist.get(adjustedCentral));
        oneSided.put(adjustedCentral,Nd4j.scalar(0.0));
        return new INDArray[] {hAdjusted,oneSided};
    }

public static INDArray [ ] adjustSchemeToBounds ( INDArray x , INDArray h , int numSteps , INDArray lowerBound , INDArray upperBound ) { INDArray oneSided = Nd4j . onesLike ( h ) ; if ( and ( lowerBound . eq ( Double . NEGATIVE_INFINITY ) , upperBound . eq ( Double . POSITIVE_INFINITY ) ) . sumNumber ( ) . doubleValue ( ) > 0 ) { return new INDArray [ ] { h , oneSided } ; } INDArray hTotal = h . mul ( numSteps ) ; INDArray hAdjusted = h . dup ( ) ; INDArray lowerDist = x . sub ( lowerBound ) ; INDArray upperBound2 = upperBound . sub ( x ) ; INDArray central = and ( greaterThanOrEqual ( lowerDist , hTotal ) , greaterThanOrEqual ( upperBound2 , hTotal ) ) ; INDArray forward = and ( greaterThanOrEqual ( upperBound , lowerDist ) , not ( central ) ) ; hAdjusted . put ( forward , min ( h . get ( forward ) , upperBound2 . get ( forward ) . mul ( 0.5 ) . divi ( numSteps ) ) ) ; oneSided . put ( forward , Nd4j . scalar ( 1.0 ) ) ; INDArray backward = and ( upperBound2 . lt ( lowerBound ) , not ( central ) ) ; hAdjusted . put ( backward , min ( h . get ( backward ) , lowerDist . get ( backward ) . mul ( 0.5 ) . divi ( numSteps ) ) ) ; oneSided . put ( backward , Nd4j . scalar ( 1.0 ) ) ; INDArray minDist = min ( upperBound2 , lowerDist ) . divi ( numSteps ) ; INDArray adjustedCentral = and ( not ( central ) , lessThanOrEqual ( abs ( hAdjusted ) , minDist ) ) ; hAdjusted . put ( adjustedCentral , minDist . get ( adjustedCentral ) ) ; oneSided . put ( adjustedCentral , Nd4j . scalar ( 0.0 ) ) ; return new INDArray [ ] { hAdjusted , oneSided } ; }

Adjust final scheme to presence of bounds

Returns (in this order):
adjusted hypothesis, whether to use onesided as an int mask array
@param x the point to estimate the derivative
@param h the finite difference steps
@param numSteps Number of h steps in 1 direction
to implement finite difference scheme.

@param lowerBound Lower bounds for independent variable variable
@param upperBound Upper bounds for independent variable
@return


@Override
    public DataSet next() {
        if (!iter.hasNext() && passes < numPasses) {
            passes++;
            batch = 0;
            log.info("Epoch " + passes + " batch " + batch);
            iter.reset();
        }
        batch++;

        DataSet next = iter.next();
        if (preProcessor != null)
            preProcessor.preProcess(next);
        return next;
    }

@
Override
public
DataSet
next
(
)
{
if
(
!
iter
.
hasNext
(
)
&&
passes
<
numPasses
)
{
passes
++
;
batch
=
0
;
log
.
info
(
"Epoch "
+
passes
+
" batch "
+
batch
)
;
iter
.
reset
(
)
;
}
batch
++
;
DataSet
next
=
iter
.
next
(
)
;
if
(
preProcessor
!=
)
preProcessor
.
preProcess
(
next
)
;
return
next
;
}

Returns the next element in the iteration.

@return the next element in the iteration

Returns the next element in the iteration .


@Override
    public void sgeqrf(int M, int N, INDArray A, INDArray R, INDArray INFO) {
        INDArray tau = Nd4j.create( N ) ;

        int status = LAPACKE_sgeqrf(getColumnOrder(A), M, N,
             (FloatPointer)A.data().addressPointer(), getLda(A),
             (FloatPointer)tau.data().addressPointer()
             );
        if( status != 0 ) {
            throw new BlasException( "Failed to execute sgeqrf", status ) ;
        }

        // Copy R ( upper part of Q ) into result
        if( R != null ) {
            R.assign( A.get( NDArrayIndex.interval( 0, A.columns() ), NDArrayIndex.all() ) ) ;
			INDArrayIndex ix[] = new INDArrayIndex[ 2 ] ;

			for( int i=1 ; i<Math.min( A.rows(), A.columns() ) ; i++ ) {
				ix[0] = NDArrayIndex.point( i ) ;
				ix[1] = NDArrayIndex.interval( 0, i ) ;
				R.put(ix, 0) ;
			}
        }

        status = LAPACKE_sorgqr( getColumnOrder(A), M, N, N,
             (FloatPointer)A.data().addressPointer(), getLda(A),
             (FloatPointer)tau.data().addressPointer()
             );
        if( status != 0 ) {
            throw new BlasException( "Failed to execute sorgqr", status ) ;
        }
    }


public static AllocationShape buildAllocationShape(DataBuffer buffer) {
        AllocationShape shape = new AllocationShape();
        shape.setStride(1);
        shape.setOffset(buffer.originalOffset());
        shape.setDataType(buffer.dataType());
        shape.setLength(buffer.length());

        return shape;
    }

public static AllocationShape buildAllocationShape ( DataBuffer buffer ) { AllocationShape shape = new AllocationShape ( ) ; shape . setStride ( 1 ) ; shape . setOffset ( buffer . originalOffset ( ) ) ; shape . setDataType ( buffer . dataType ( ) ) ; shape . setLength ( buffer . length ( ) ) ; return shape ; }

This method returns AllocationShape for the whole DataBuffer.

@param buffer
@return

This method returns AllocationShape for the whole DataBuffer .


public static boolean nameExistsInPath(String name) {
        String path = System.getenv(PATH_ENV_VARIABLE);
        String[] dirs = path.split(File.pathSeparator);
        for (String dir : dirs) {
            File dirFile = new File(dir);
            if (!dirFile.exists())
                continue;

            if (dirFile.isFile() && dirFile.getName().equals(name))
                return true;
            else {
                Iterator<File> files = FileUtils.iterateFiles(dirFile, null, false);
                while (files.hasNext()) {
                    File curr = files.next();
                    if (curr.getName().equals(name))
                        return true;
                }

            }
        }

        return false;
    }

public static boolean nameExistsInPath ( String name ) { String path = System . getenv ( PATH_ENV_VARIABLE ) ; String [ ] dirs = path . split ( File . pathSeparator ) ; for ( String dir : dirs ) { File dirFile = new File ( dir ) ; if ( ! dirFile . exists ( ) ) continue ; if ( dirFile . isFile ( ) && dirFile . getName ( ) . equals ( name ) ) return true ; else { Iterator < File > files = FileUtils . iterateFiles ( dirFile , null , false ) ; while ( files . hasNext ( ) ) { File curr = files . next ( ) ; if ( curr . getName ( ) . equals ( name ) ) return true ; } } } return false ; }

Check if a file exists in the path
@param name the name of the file
@return true if the name exists
false otherwise


protected void read(ObjectInputStream s) throws IOException, ClassNotFoundException {
        data = Nd4j.createBuffer(length, false);
        data.read(s);
    }

protected void read ( ObjectInputStream s ) throws IOException , ClassNotFoundException { data = Nd4j . createBuffer ( length , false ) ; data . read ( s ) ; }

Custom deserialization for Java serialization


protected void sweepTail() {
        Integer deviceId = allocator.getDeviceId();
        int cnt = 0;

        // we get number of issued commands for specific device
        long lastCommandId = deviceClocks.get(deviceId).get();

        for (int l = 0; l < configuration.getCommandLanesNumber(); l++) {
            Queue<cudaEvent_t> queue = eventsBarrier.get(deviceId).get(l);

            if (queue.size() >= MAX_EXECUTION_QUEUE
                            || laneClocks.get(deviceId).get(l).get() < lastCommandId - MAX_EXECUTION_QUEUE) {
                cudaEvent_t event = queue.poll();
                if (event != null && !event.isDestroyed()) {
                    event.synchronize();
                    event.destroy();
                    cnt++;
                }
            }

        }

        deviceClocks.get(deviceId).incrementAndGet();

        //  log.info("Events sweeped: [{}]", cnt);
    }

This method ensures the events in the beginning of FIFO queues are finished


@Override
    public INDArray createFromNpyPointer(Pointer pointer) {
        Pointer dataPointer = nativeOps.dataPointForNumpy(pointer);
        int dataBufferElementSize = nativeOps.elementSizeForNpyArray(pointer);

        DataBuffer data = null;
        Pointer shapeBufferPointer = nativeOps.shapeBufferForNumpy(pointer);
        int length = nativeOps.lengthForShapeBufferPointer(shapeBufferPointer);
        shapeBufferPointer.capacity(4 * length);
        shapeBufferPointer.limit(4 * length);
        shapeBufferPointer.position(0);

        val intPointer = new LongPointer(shapeBufferPointer);

        DataBuffer shapeBuffer = Nd4j.createBuffer(shapeBufferPointer, DataBuffer.Type.LONG,length, LongRawIndexer.create(intPointer));

        dataPointer.position(0);
        dataPointer.limit(dataBufferElementSize * Shape.length(shapeBuffer));
        dataPointer.capacity(dataBufferElementSize * Shape.length(shapeBuffer));

        // we don't care about pointers here, they will be copied in BaseCudaDataBuffer method, and indexer will be recreated
        if(dataBufferElementSize == (Float.SIZE / 8)) {
            data = Nd4j.createBuffer(dataPointer,
                    DataBuffer.Type.FLOAT,
                    Shape.length(shapeBuffer),
                    FloatIndexer.create(new FloatPointer(dataPointer)));
        }
        else if(dataBufferElementSize == (Double.SIZE / 8)) {
            data = Nd4j.createBuffer(dataPointer,
                    DataBuffer.Type.DOUBLE,
                    Shape.length(shapeBuffer),
                    DoubleIndexer.create(new DoublePointer(dataPointer)));
        }

        INDArray ret = Nd4j.create(data,Shape.shape(shapeBuffer),
                Shape.strideArr(shapeBuffer),Shape.offset(shapeBuffer),Shape.order(shapeBuffer));
        return ret;
    }

Create from an in memory numpy pointer

@param pointer the pointer to the
numpy array
@return an ndarray created from the in memory
numpy pointer


@Override
    public INDArray createFromNpyFile(File file) {
        /*Pointer pointer = nativeOps.numpyFromFile(new BytePointer(file.getAbsolutePath().getBytes()));
        log.info("Pointer here: {}", pointer.address());
        return createFromNpyPointer(pointer);

        */

        byte[] pathBytes = file.getAbsolutePath().getBytes(Charset.forName("UTF-8" ));
        String otherBytes = new String(pathBytes);
        System.out.println(otherBytes);
        ByteBuffer directBuffer = ByteBuffer.allocateDirect(pathBytes.length).order(ByteOrder.nativeOrder());
        directBuffer.put(pathBytes);
        directBuffer.rewind();
        directBuffer.position(0);
        Pointer pointer = nativeOps.numpyFromFile(new BytePointer(directBuffer));
        INDArray result = createFromNpyPointer(pointer);

        // releasing original pointer here
        nativeOps.releaseNumpy(pointer);

        return result;
    }

Create from a given numpy file.

@param file the file to create the ndarray from
@return the created ndarray


@Override
    public PagedPointer alloc(long requiredMemory, MemoryKind kind, DataBuffer.Type dataType, boolean initialize) {
        throw new UnsupportedOperationException("DummyWorkspace shouldn't be used for allocation");
    }

This method does allocation from a given Workspace

@param requiredMemory allocation size, in bytes
@param kind           MemoryKind for allocation
@param dataType       dataType that is going to be used
@param initialize
@return


@Override
    public void attachObject(Object object) {
        if (!objectLocks.containsKey(object))
            objectLocks.put(object, new ReentrantReadWriteLock());
    }

@ Override public void attachObject ( Object object ) { if ( ! objectLocks . containsKey ( object ) ) objectLocks . put ( object , new ReentrantReadWriteLock ( ) ) ; }

This method notifies locker, that specific object was added to tracking list

@param object

This method notifies locker that specific object was added to tracking list


public boolean started() {
        return master.equals(ServerState.STARTED.name().toLowerCase())
                        && responder.equals(ServerState.STARTED.name().toLowerCase());
    }

public boolean started ( ) { return master . equals ( ServerState . STARTED . name ( ) . toLowerCase ( ) ) && responder . equals ( ServerState . STARTED . name ( ) . toLowerCase ( ) ) ; }

Returns true if bth
the master and responder are started.
@return

Returns true if bth the master and responder are started .


@Override
    public Op exec(Op op) {
        /*
            We pass this op to GridProcessor through check for possible MetaOp concatenation
            Also, it's the GriOp entry point
         */
        checkForCompression(op);

        invokeWatchdog(op);

        if (op instanceof Accumulation) {
            exec((Accumulation) op, new int[] {Integer.MAX_VALUE});
        } else if (op instanceof IndexAccumulation) {
            exec((IndexAccumulation) op, new int[] {Integer.MAX_VALUE});
        } else if (op instanceof ScalarOp || op instanceof TransformOp) {
            // the only entry place for TADless ops
            processAsGridOp(op);
        } else if (op instanceof BroadcastOp) {
            invoke((BroadcastOp) op);
        } else {
            //logger.info("Random op: {}", op.getClass().getSimpleName());
            pushToGrid(new OpDescriptor(op));
        }

        return op;
    }

This is one of the main entry points for ops that are executed without respect to dimension.

Developers note: For CudaGridExecutioner that's also the MetaOp/GridOp creation point.

@param op
@return

This is one of the main entry points for ops that are executed without respect to dimension .


@Override
    public void flushQueueBlocking() {
        flushQueue();

        //    logger.info("Blocking flush");n

        ((CudaContext) AtomicAllocator.getInstance().getDeviceContext().getContext()).syncOldStream();
        ((CudaContext) AtomicAllocator.getInstance().getDeviceContext().getContext()).syncSpecialStream();
    }

@
Override
public
void
flushQueueBlocking
(
)
{
flushQueue
(
)
;
//    logger.info("Blocking flush");n
(
(
CudaContext
)
AtomicAllocator
.
getInstance
(
)
.
getDeviceContext
(
)
.
getContext
(
)
)
.
syncOldStream
(
)
;
(
(
CudaContext
)
AtomicAllocator
.
getInstance
(
)
.
getDeviceContext
(
)
.
getContext
(
)
)
.
syncSpecialStream
(
)
;
}

This method forces all currently enqueued ops to be executed immediately

PLEASE NOTE: This call is always blocking, until all queued operations are finished


public InputStream getInputStream() throws FileNotFoundException {
        URL url = this.getUrl();
        if (isJarURL(url)) {
            try {
                url = extractActualUrl(url);
                ZipFile zipFile = new ZipFile(url.getFile());
                ZipEntry entry = zipFile.getEntry(this.resourceName);

                InputStream stream = zipFile.getInputStream(entry);
                return stream;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            File srcFile = this.getFile();
            return new FileInputStream(srcFile);
        }
    }

public InputStream getInputStream ( ) throws FileNotFoundException { URL url = this . getUrl ( ) ; if ( isJarURL ( url ) ) { try { url = extractActualUrl ( url ) ; ZipFile zipFile = new ZipFile ( url . getFile ( ) ) ; ZipEntry entry = zipFile . getEntry ( this . resourceName ) ; InputStream stream = zipFile . getInputStream ( entry ) ; return stream ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; } } else { File srcFile = this . getFile ( ) ; return new FileInputStream ( srcFile ) ; } }

Returns requested ClassPathResource as InputStream object

@return File requested at constructor call
@throws FileNotFoundException


@Override
    public Integer getDeviceForThread(long threadId) {
        if (getNumberOfDevices() == 1)
            return 0;

        Integer aff = affinityMap.get(threadId);

        if (aff == null) {
            Integer deviceId = getNextDevice(threadId);
            affinityMap.put(threadId, deviceId);
            affiliated.set(new AtomicBoolean(false));

            if (threadId == Thread.currentThread().getId()) {
                NativeOpsHolder.getInstance().getDeviceNativeOps().setDevice(new CudaPointer(deviceId));
                //logger.error("setDevice({}) called for thread {}", deviceId, Thread.currentThread().getName());
                affiliated.get().set(true);
            }

            return deviceId;
        } else {

            if (threadId == Thread.currentThread().getId()) {
                if (affiliated.get() == null)
                    affiliated.set(new AtomicBoolean(false));

                if (!affiliated.get().get()) {
                    NativeOpsHolder.getInstance().getDeviceNativeOps().setDevice(new CudaPointer(aff));
                    //logger.error("SCARY setDevice({}) called for thread {}", aff, threadId);
                    affiliated.get().set(true);
                    return aff;
                }
            }

            return aff;
        }
/*

        return affinityMap.get(threadId);
*/
        //return 0;
    }

/*

        return affinityMap.get(threadId);
*/

This method returns deviceId for given thread, identified by threadId

If no device was assigned to this thread before this call, it'll be assinged here.

@param threadId
@return

This method returns deviceId for given thread identified by threadId


@Override
    public void attachThreadToDevice(long threadId, Integer deviceId) {
        List<Integer> devices = new ArrayList<>(CudaEnvironment.getInstance().getConfiguration().getAvailableDevices());
        logger.debug("Manually mapping thread [{}] to device [{}], out of [{}] devices...", threadId, deviceId,
                        devices.size());
        affinityMap.put(threadId, deviceId);
    }

This method pairs specified thread & device

@param threadId
@param deviceId


protected Integer getNextDevice(long threadId) {
        Integer device = null;
        if (!CudaEnvironment.getInstance().getConfiguration().isForcedSingleGPU() && getNumberOfDevices() > 0) {
            // simple round-robin here
            synchronized (this) {
                device = CudaEnvironment.getInstance().getConfiguration().getAvailableDevices().get(devPtr.getAndIncrement());

                // We check only for number of entries here, not their actual values
                if (devPtr.get() >= CudaEnvironment.getInstance().getConfiguration().getAvailableDevices().size())
                    devPtr.set(0);

                logger.debug("Mapping thread [{}] to device [{}], out of [{}] devices...", threadId, device,
                        CudaEnvironment.getInstance().getConfiguration().getAvailableDevices().size());
            }
        } else {
            device = CudaEnvironment.getInstance().getConfiguration().getAvailableDevices().get(0);
            logger.debug("Single device is forced, mapping to device [{}]", device);
        }

        return device;
    }

This method returns device id available. Round-robin balancing used here.

@param threadId this parameter can be anything, it's used for logging only.
@return

This method returns device id available . Round - robin balancing used here .


public static String getOsName() {
        OSType osType = calculateOS();
        switch (osType) {
            case APPLE:
                return "macosx";
            case LINUX:
                return "linux";
            case SUN:
                return "sun";
            case WINDOWS:
                return "windows";
        }
        return "";
    }

public static String getOsName ( ) { OSType osType = calculateOS ( ) ; switch ( osType ) { case APPLE : return "macosx" ; case LINUX : return "linux" ; case SUN : return "sun" ; case WINDOWS : return "windows" ; } return "" ; }

Get the name of the os
for libary discovery on the classpath
@return


public static ARCHType calculateArch() {
        String osArch = System.getProperty("os.arch");
        osArch = osArch.toLowerCase(Locale.ENGLISH);
        if (osArch.equals("i386") || osArch.equals("x86") || osArch.equals("i686")) {
            return ARCHType.X86;
        }
        if (osArch.startsWith("amd64") || osArch.startsWith("x86_64")) {
            return ARCHType.X86_64;
        }
        if (osArch.equals("ppc") || osArch.equals("powerpc")) {
            return ARCHType.PPC;
        }
        if (osArch.startsWith("ppc")) {
            return ARCHType.PPC_64;
        }
        if (osArch.startsWith("sparc")) {
            return ARCHType.SPARC;
        }
        if (osArch.startsWith("arm")) {
            return ARCHType.ARM;
        }
        if (osArch.startsWith("mips")) {
            return ARCHType.MIPS;
        }
        if (osArch.contains("risc")) {
            return ARCHType.RISC;
        }
        return ARCHType.UNKNOWN;
    }

public static ARCHType calculateArch ( ) { String osArch = System . getProperty ( "os.arch" ) ; osArch = osArch . toLowerCase ( Locale . ENGLISH ) ; if ( osArch . equals ( "i386" ) || osArch . equals ( "x86" ) || osArch . equals ( "i686" ) ) { return ARCHType . X86 ; } if ( osArch . startsWith ( "amd64" ) || osArch . startsWith ( "x86_64" ) ) { return ARCHType . X86_64 ; } if ( osArch . equals ( "ppc" ) || osArch . equals ( "powerpc" ) ) { return ARCHType . PPC ; } if ( osArch . startsWith ( "ppc" ) ) { return ARCHType . PPC_64 ; } if ( osArch . startsWith ( "sparc" ) ) { return ARCHType . SPARC ; } if ( osArch . startsWith ( "arm" ) ) { return ARCHType . ARM ; } if ( osArch . startsWith ( "mips" ) ) { return ARCHType . MIPS ; } if ( osArch . contains ( "risc" ) ) { return ARCHType . RISC ; } return ARCHType . UNKNOWN ; }

Calculates the current ARCHType

@return The current ARCHType


public void publish(INDArray arr) {
        if (producerTemplate == null)
            producerTemplate = camelContext.createProducerTemplate();
        producerTemplate.sendBody("direct:start", arr);
    }

public void publish ( INDArray arr ) { if ( producerTemplate == null ) producerTemplate = camelContext . createProducerTemplate ( ) ; producerTemplate . sendBody ( "direct:start" , arr ) ; }

Publish to a kafka topic
based on the connection information
@param arr


public void start() {
        try {
            InputStream is = new ClassPathResource(resourcePath, InstrumentationApplication.class.getClassLoader())
                            .getInputStream();
            File tmpConfig = new File(resourcePath);
            if (!tmpConfig.getParentFile().exists())
                tmpConfig.getParentFile().mkdirs();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmpConfig));
            IOUtils.copy(is, bos);
            bos.flush();
            run(new String[] {"server", tmpConfig.getAbsolutePath()});
            tmpConfig.deleteOnExit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

public void start ( ) { try { InputStream is = new ClassPathResource ( resourcePath , InstrumentationApplication . class . getClassLoader ( ) ) . getInputStream ( ) ; File tmpConfig = new File ( resourcePath ) ; if ( ! tmpConfig . getParentFile ( ) . exists ( ) ) tmpConfig . getParentFile ( ) . mkdirs ( ) ; BufferedOutputStream bos = new BufferedOutputStream ( new FileOutputStream ( tmpConfig ) ) ; IOUtils . copy ( is , bos ) ; bos . flush ( ) ; run ( new String [ ] { "server" , tmpConfig . getAbsolutePath ( ) } ) ; tmpConfig . deleteOnExit ( ) ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; } }


@Override
    public DataBuffer create(Pointer pointer, DataBuffer.Type type, long length, Indexer indexer) {
        switch (type) {
            case INT:
                return new IntBuffer(pointer, indexer, length);
            case DOUBLE:
                return new DoubleBuffer(pointer, indexer, length);
            case FLOAT:
                return new FloatBuffer(pointer, indexer, length);
            case LONG:
                return new LongBuffer(pointer, indexer, length);
        }
        throw new IllegalArgumentException("Invalid opType " + type);
    }

@
Override
public
DataBuffer
create
(
Pointer
pointer
,
DataBuffer
.
Type
type
,
long
length
,
Indexer
indexer
)
{
switch
(
type
)
{
case
INT
:
return
new
IntBuffer
(
pointer
,
indexer
,
length
)
;
case
DOUBLE
:
return
new
DoubleBuffer
(
pointer
,
indexer
,
length
)
;
case
FLOAT
:
return
new
FloatBuffer
(
pointer
,
indexer
,
length
)
;
case
LONG
:
return
new
LongBuffer
(
pointer
,
indexer
,
length
)
;
}
throw
new
IllegalArgumentException
(
"Invalid opType "
+
type
)
;
}

Create a data buffer based on the
given pointer, data buffer opType,
and length of the buffer

@param pointer the pointer to use
@param type    the opType of buffer
@param length  the length of the buffer
@param indexer the indexer for the pointer
@return the data buffer
backed by this pointer with the given
opType and length.

Create a data buffer based on the given pointer data buffer opType and length of the buffer


protected void interceptIntDataType(Op op) {
        // FIXME: Remove this method, after we'll add support for <int> dtype operations

        if (op.x() != null && op.x().data().dataType() == DataBuffer.Type.INT)
            throw new ND4JIllegalStateException(
                            "Op.X contains INT data. Operations on INT dataType are not supported yet");

        if (op.z() != null && op.z().data().dataType() == DataBuffer.Type.INT)
            throw new ND4JIllegalStateException(
                            "Op.Z contains INT data. Operations on INT dataType are not supported yet");

        if (op.y() != null && op.y().data().dataType() == DataBuffer.Type.INT)
            throw new ND4JIllegalStateException(
                            "Op.Y contains INT data. Operations on INT dataType are not supported yet.");
    }

This method checks if any Op operand has data opType of INT, and throws exception if any.

@param op

This method checks if any Op operand has data opType of INT and throws exception if any .


@Override
    public IComplexNumber addi(IComplexNumber c, IComplexNumber result) {
        return result.set(result.realComponent().floatValue() + c.realComponent().floatValue(),
                        result.imaginaryComponent().floatValue() + c.imaginaryComponent().floatValue());
    }

@ Override public IComplexNumber addi ( IComplexNumber c , IComplexNumber result ) { return result . set ( result . realComponent ( ) . floatValue ( ) + c . realComponent ( ) . floatValue ( ) , result . imaginaryComponent ( ) . floatValue ( ) + c . imaginaryComponent ( ) . floatValue ( ) ) ; }

Add two complex numbers in-place

@param c
@param result


@Override
    public void processMessage() {
        if (payload != null) {
            // we're assigning array
            if (storage.arrayExists(key) && storage.getArray(key).length() == payload.length())
                storage.getArray(key).assign(payload);
            else
                storage.setArray(key, payload);
        } else {
            // we're assigning number to row
            if (index >= 0) {
                if (storage.getArray(key) == null)
                    throw new RuntimeException("Init wasn't called before for key [" + key + "]");
                storage.getArray(key).getRow(index).assign(value);
            } else
                storage.getArray(key).assign(value);
        }
    }

@
Override
public
void
processMessage
(
)
{
if
(
payload
!=
)
{
// we're assigning array
if
(
storage
.
arrayExists
(
key
)
&&
storage
.
getArray
(
key
)
.
length
(
)
==
payload
.
length
(
)
)
storage
.
getArray
(
key
)
.
assign
(
payload
)
;
else
storage
.
setArray
(
key
,
payload
)
;
}
else
{
// we're assigning number to row
if
(
index
>=
0
)
{
if
(
storage
.
getArray
(
key
)
==
)
throw
new
RuntimeException
(
"Init wasn't called before for key ["
+
key
+
"]"
)
;
storage
.
getArray
(
key
)
.
getRow
(
index
)
.
assign
(
value
)
;
}
else
storage
.
getArray
(
key
)
.
assign
(
value
)
;
}
}

This method assigns specific value to either specific row, or whole array.
Array is identified by key

This method assigns specific value to either specific row or whole array . Array is identified by key


public SDVariable avgPooling3d(SDVariable[] inputs, Pooling3DConfig pooling3DConfig) {
        Pooling3D maxPooling3D = Pooling3D.builder()
                .inputs(inputs)
                .sameDiff(sameDiff())
                .pooling3DConfig(pooling3DConfig)
                .type(Pooling3D.Pooling3DType.AVG)
                .build();

        return maxPooling3D.outputVariables()[0];
    }

public SDVariable avgPooling3d ( SDVariable [ ] inputs , Pooling3DConfig pooling3DConfig ) { Pooling3D maxPooling3D = Pooling3D . builder ( ) . inputs ( inputs ) . sameDiff ( sameDiff ( ) ) . pooling3DConfig ( pooling3DConfig ) . type ( Pooling3D . Pooling3DType . AVG ) . build ( ) ; return maxPooling3D . outputVariables ( ) [ 0 ] ; }

Avg pooling 3d operation.

@param inputs          the inputs to pooling
@param pooling3DConfig the configuration
@return


public SDVariable depthWiseConv2d(SDVariable[] inputs, Conv2DConfig depthConv2DConfig) {
        SConv2D depthWiseConv2D = SConv2D.sBuilder()
                .inputFunctions(inputs)
                .sameDiff(sameDiff())
                .conv2DConfig(depthConv2DConfig)
                .build();

        return depthWiseConv2D.outputVariables()[0];
    }

public SDVariable depthWiseConv2d ( SDVariable [ ] inputs , Conv2DConfig depthConv2DConfig ) { SConv2D depthWiseConv2D = SConv2D . sBuilder ( ) . inputFunctions ( inputs ) . sameDiff ( sameDiff ( ) ) . conv2DConfig ( depthConv2DConfig ) . build ( ) ; return depthWiseConv2D . outputVariables ( ) [ 0 ] ; }

Depthwise Conv2d operation. This is just separable convolution with
only the depth-wise weights specified.

@param inputs            the inputs to conv2d
@param depthConv2DConfig the configuration
@return

Depthwise Conv2d operation . This is just separable convolution with only the depth - wise weights specified .


public void reset() {
        invocationsCount.set(0);

        classAggergator.reset();
        longAggergator.reset();
        classCounter.reset();
        opCounter.reset();
        classPairsCounter.reset();
        opPairsCounter.reset();
        matchingCounter.reset();
        matchingCounterDetailed.reset();
        matchingCounterInverted.reset();
        methodsAggregator.reset();

        scalarAggregator.reset();
        nonEwsAggregator.reset();
        stridedAggregator.reset();
        tadNonEwsAggregator.reset();
        tadStridedAggregator.reset();
        mixedOrderAggregator.reset();

        blasAggregator.reset();
        blasOrderCounter.reset();

        orderCounter.reset();
        listeners.clear();
    }

public void reset ( ) { invocationsCount . set ( 0 ) ; classAggergator . reset ( ) ; longAggergator . reset ( ) ; classCounter . reset ( ) ; opCounter . reset ( ) ; classPairsCounter . reset ( ) ; opPairsCounter . reset ( ) ; matchingCounter . reset ( ) ; matchingCounterDetailed . reset ( ) ; matchingCounterInverted . reset ( ) ; methodsAggregator . reset ( ) ; scalarAggregator . reset ( ) ; nonEwsAggregator . reset ( ) ; stridedAggregator . reset ( ) ; tadNonEwsAggregator . reset ( ) ; tadStridedAggregator . reset ( ) ; mixedOrderAggregator . reset ( ) ; blasAggregator . reset ( ) ; blasOrderCounter . reset ( ) ; orderCounter . reset ( ) ; listeners . clear ( ) ; }


protected String getOpClass(Op op) {
        if (op instanceof ScalarOp) {
            return "ScalarOp";
        } else if (op instanceof MetaOp) {
            return "MetaOp";
        } else if (op instanceof GridOp) {
            return "GridOp";
        } else if (op instanceof BroadcastOp) {
            return "BroadcastOp";
        } else if (op instanceof RandomOp) {
            return "RandomOp";
        } else if (op instanceof Accumulation) {
            return "AccumulationOp";
        } else if (op instanceof TransformOp) {
            if (op.y() == null) {
                return "TransformOp";
            } else
                return "PairWiseTransformOp";
        } else if (op instanceof IndexAccumulation) {
            return "IndexAccumulationOp";
        } else if (op instanceof CustomOp) {
            return "CustomOp";
        }else
            return "Unknown Op calls";
    }

protected
String
getOpClass
(
Op
op
)
{
if
(
op
instanceof
ScalarOp
)
{
return
"ScalarOp"
;
}
else
if
(
op
instanceof
MetaOp
)
{
return
"MetaOp"
;
}
else
if
(
op
instanceof
GridOp
)
{
return
"GridOp"
;
}
else
if
(
op
instanceof
BroadcastOp
)
{
return
"BroadcastOp"
;
}
else
if
(
op
instanceof
RandomOp
)
{
return
"RandomOp"
;
}
else
if
(
op
instanceof
Accumulation
)
{
return
"AccumulationOp"
;
}
else
if
(
op
instanceof
TransformOp
)
{
if
(
op
.
y
(
)
==
)
{
return
"TransformOp"
;
}
else
return
"PairWiseTransformOp"
;
}
else
if
(
op
instanceof
IndexAccumulation
)
{
return
"IndexAccumulationOp"
;
}
else
if
(
op
instanceof
CustomOp
)
{
return
"CustomOp"
;
}
else
return
"Unknown Op calls"
;
}

This method returns op class opName

@param op
@return


public INDArray storeAndAllocateNewArray() {
        val shape = sameDiff.getShapeForVarName(getVarName());
        if(getArr() != null && Arrays.equals(getArr().shape(),shape))
            return getArr();

        if(varName == null)
            throw new ND4JIllegalStateException("Unable to store array for null variable name!");

        if(shape == null) {
            throw new ND4JIllegalStateException("Unable to allocate new array. No shape found for variable " + varName);
        }

        val arr = getWeightInitScheme().create(shape);
        sameDiff.putArrayForVarName(getVarName(),arr);
        return arr;
    }

Allocate and return a  new array
based on the vertex id and weight initialization.
@return the allocated array

Allocate and return a new array based on the vertex id and weight initialization .


public long[] getShape() {
        long[] initialShape =  sameDiff.getShapeForVarName(getVarName());
        if(initialShape == null) {
            val arr = getArr();
            if(arr != null)
                return arr.shape();
        }

        return initialShape;
    }

public long [ ] getShape ( ) { long [ ] initialShape = sameDiff . getShapeForVarName ( getVarName ( ) ) ; if ( initialShape == null ) { val arr = getArr ( ) ; if ( arr != null ) return arr . shape ( ) ; } return initialShape ; }

Returns the shape of this variable
@return


public INDArray eval() {
        SameDiff exec = sameDiff.dup();
        exec.defineFunction("output", new SameDiff.SameDiffFunctionDefinition() {
            @Override
            public SDVariable[] define(SameDiff sameDiff, Map<String, INDArray> inputs, SDVariable[] variableInputs) {
                return new SDVariable[] { SDVariable.this};
            }
        });

        SDVariable output = exec.invokeFunctionOn("output",exec);
        return output.getSameDiff().execAndEndResult();
    }

public INDArray eval ( ) { SameDiff exec = sameDiff . dup ( ) ; exec . defineFunction ( "output" , new SameDiff . SameDiffFunctionDefinition ( ) { @ Override public SDVariable [ ] define ( SameDiff sameDiff , Map < String , INDArray > inputs , SDVariable [ ] variableInputs ) { return new SDVariable [ ] { SDVariable . this } ; } } ) ; SDVariable output = exec . invokeFunctionOn ( "output" , exec ) ; return output . getSameDiff ( ) . execAndEndResult ( ) ; }

Evaluate the result of this variable
@return


@Override
    public INDArray compress(double[] data, int[] shape, char order) {
        DoublePointer pointer = new DoublePointer(data);

        DataBuffer shapeInfo = Nd4j.getShapeInfoProvider().createShapeInformation(shape, order).getFirst();
        DataBuffer buffer = compressPointer(DataBuffer.TypeEx.DOUBLE, pointer, data.length, 8);

        return Nd4j.createArrayFromShapeBuffer(buffer, shapeInfo);
    }

@ Override public INDArray compress ( double [ ] data , int [ ] shape , char order ) { DoublePointer pointer = new DoublePointer ( data ) ; DataBuffer shapeInfo = Nd4j . getShapeInfoProvider ( ) . createShapeInformation ( shape , order ) . getFirst ( ) ; DataBuffer buffer = compressPointer ( DataBuffer . TypeEx . DOUBLE , pointer , data . length , 8 ) ; return Nd4j . createArrayFromShapeBuffer ( buffer , shapeInfo ) ; }

This method creates compressed INDArray from Java double array, skipping usual INDArray instantiation routines

@param data
@param shape
@param order
@return

This method creates compressed INDArray from Java double array skipping usual INDArray instantiation routines


public static IComplexNDArray expi(IComplexNDArray toExp) {
        IComplexNDArray flattened = toExp.ravel();
        for (int i = 0; i < flattened.length(); i++) {
            IComplexNumber n = flattened.getComplex(i);
            flattened.put(i, Nd4j.scalar(ComplexUtil.exp(n)));
        }
        return flattened.reshape(toExp.shape());
    }

public static IComplexNDArray expi ( IComplexNDArray toExp ) { IComplexNDArray flattened = toExp . ravel ( ) ; for ( int i = 0 ; i < flattened . length ( ) ; i ++ ) { IComplexNumber n = flattened . getComplex ( i ) ; flattened . put ( i , Nd4j . scalar ( ComplexUtil . exp ( n ) ) ) ; } return flattened . reshape ( toExp . shape ( ) ) ; }

Returns the exponential of a complex ndarray

@param toExp the ndarray to convert
@return the exponential of the specified
ndarray


public static IComplexNDArray center(IComplexNDArray arr, long[] shape) {
        if (arr.length() < ArrayUtil.prod(shape))
            return arr;
        for (int i = 0; i < shape.length; i++)
            if (shape[i] < 1)
                shape[i] = 1;

        INDArray shapeMatrix = NDArrayUtil.toNDArray(shape);
        INDArray currShape = NDArrayUtil.toNDArray(arr.shape());

        INDArray startIndex = Transforms.floor(currShape.sub(shapeMatrix).divi(Nd4j.scalar(2)));
        INDArray endIndex = startIndex.add(shapeMatrix);
        INDArrayIndex[] indexes = Indices.createFromStartAndEnd(startIndex, endIndex);

        if (shapeMatrix.length() > 1)
            return arr.get(indexes);

        else {
            IComplexNDArray ret = Nd4j.createComplex(new int[] {(int) shapeMatrix.getDouble(0)});
            int start = (int) startIndex.getDouble(0);
            int end = (int) endIndex.getDouble(0);
            int count = 0;
            for (int i = start; i < end; i++) {
                ret.putScalar(count++, arr.getComplex(i));
            }

            return ret;
        }

    }

public static IComplexNDArray center ( IComplexNDArray arr , long [ ] shape ) { if ( arr . length ( ) < ArrayUtil . prod ( shape ) ) return arr ; for ( int i = 0 ; i < shape . length ; i ++ ) if ( shape [ i ] < 1 ) shape [ i ] = 1 ; INDArray shapeMatrix = NDArrayUtil . toNDArray ( shape ) ; INDArray currShape = NDArrayUtil . toNDArray ( arr . shape ( ) ) ; INDArray startIndex = Transforms . floor ( currShape . sub ( shapeMatrix ) . divi ( Nd4j . scalar ( 2 ) ) ) ; INDArray endIndex = startIndex . add ( shapeMatrix ) ; INDArrayIndex [ ] indexes = Indices . createFromStartAndEnd ( startIndex , endIndex ) ; if ( shapeMatrix . length ( ) > 1 ) return arr . get ( indexes ) ; else { IComplexNDArray ret = Nd4j . createComplex ( new int [ ] { ( int ) shapeMatrix . getDouble ( 0 ) } ) ; int start = ( int ) startIndex . getDouble ( 0 ) ; int end = ( int ) endIndex . getDouble ( 0 ) ; int count = 0 ; for ( int i = start ; i < end ; i ++ ) { ret . putScalar ( count ++ , arr . getComplex ( i ) ) ; } return ret ; } }

Center an array

@param arr   the arr to center
@param shape the shape of the array
@return the center portion of the array based on the
specified shape


public static IComplexNDArray truncate(IComplexNDArray nd, int n, int dimension) {

        if (nd.isVector()) {
            IComplexNDArray truncated = Nd4j.createComplex(new int[] {1, n});
            for (int i = 0; i < n; i++)
                truncated.putScalar(i, nd.getComplex(i));

            return truncated;
        }

        if (nd.size(dimension) > n) {
            long[] shape = ArrayUtil.copy(nd.shape());
            shape[dimension] = n;
            IComplexNDArray ret = Nd4j.createComplex(shape);
            IComplexNDArray ndLinear = nd.linearView();
            IComplexNDArray retLinear = ret.linearView();
            for (int i = 0; i < ret.length(); i++)
                retLinear.putScalar(i, ndLinear.getComplex(i));
            return ret;

        }

        return nd;

    }

public static IComplexNDArray truncate ( IComplexNDArray nd , int n , int dimension ) { if ( nd . isVector ( ) ) { IComplexNDArray truncated = Nd4j . createComplex ( new int [ ] { 1 , n } ) ; for ( int i = 0 ; i < n ; i ++ ) truncated . putScalar ( i , nd . getComplex ( i ) ) ; return truncated ; } if ( nd . size ( dimension ) > n ) { long [ ] shape = ArrayUtil . copy ( nd . shape ( ) ) ; shape [ dimension ] = n ; IComplexNDArray ret = Nd4j . createComplex ( shape ) ; IComplexNDArray ndLinear = nd . linearView ( ) ; IComplexNDArray retLinear = ret . linearView ( ) ; for ( int i = 0 ; i < ret . length ( ) ; i ++ ) retLinear . putScalar ( i , ndLinear . getComplex ( i ) ) ; return ret ; } return nd ; }

Truncates an ndarray to the specified shape.
If the shape is the same or greater, it just returns
the original array

@param nd the ndarray to truncate
@param n  the number of elements to truncate to
@return the truncated ndarray

Truncates an ndarray to the specified shape . If the shape is the same or greater it just returns the original array


public static IComplexNDArray padWithZeros(IComplexNDArray nd, long[] targetShape) {
        if (Arrays.equals(nd.shape(), targetShape))
            return nd;
        //no padding required
        if (ArrayUtil.prod(nd.shape()) >= ArrayUtil.prod(targetShape))
            return nd;

        IComplexNDArray ret = Nd4j.createComplex(targetShape);
        INDArrayIndex[] targetShapeIndex = NDArrayIndex.createCoveringShape(nd.shape());
        ret.put(targetShapeIndex, nd);
        return ret;

    }

public
static
IComplexNDArray
padWithZeros
(
IComplexNDArray
nd
,
long
[
]
targetShape
)
{
if
(
Arrays
.
equals
(
nd
.
shape
(
)
,
targetShape
)
)
return
nd
;
//no padding required
if
(
ArrayUtil
.
prod
(
nd
.
shape
(
)
)
>=
ArrayUtil
.
prod
(
targetShape
)
)
return
nd
;
IComplexNDArray
ret
=
Nd4j
.
createComplex
(
targetShape
)
;
INDArrayIndex
[
]
targetShapeIndex
=
NDArrayIndex
.
createCoveringShape
(
nd
.
shape
(
)
)
;
ret
.
put
(
targetShapeIndex
,
nd
)
;
return
ret
;
}

Pads an ndarray with zeros

@param nd          the ndarray to pad
@param targetShape the the new shape
@return the padded ndarray


@Override
    public int iamax(INDArray arr) {
        switch (arr.data().dataType()) {
            case DOUBLE:
                DefaultOpExecutioner.validateDataType(DataBuffer.Type.DOUBLE, arr);
                return idamax(arr.length(), arr, 1);
            case FLOAT:
                DefaultOpExecutioner.validateDataType(DataBuffer.Type.FLOAT, arr);
                return isamax(arr.length(), arr, 1);
            case HALF:
                DefaultOpExecutioner.validateDataType(DataBuffer.Type.HALF, arr);
                return ihamax(arr.length(), arr, 1);
            default:
        }
        throw new UnsupportedOperationException();
    }

@ Override public int iamax ( INDArray arr ) { switch ( arr . data ( ) . dataType ( ) ) { case DOUBLE : DefaultOpExecutioner . validateDataType ( DataBuffer . Type . DOUBLE , arr ) ; return idamax ( arr . length ( ) , arr , 1 ) ; case FLOAT : DefaultOpExecutioner . validateDataType ( DataBuffer . Type . FLOAT , arr ) ; return isamax ( arr . length ( ) , arr , 1 ) ; case HALF : DefaultOpExecutioner . validateDataType ( DataBuffer . Type . HALF , arr ) ; return ihamax ( arr . length ( ) , arr , 1 ) ; default : } throw new UnsupportedOperationException ( ) ; }

Find the index of the element with maximum absolute value

@param arr a vector
@return the index of the element with maximum absolute value


public void broadcast(INDArray array) {
        if (array == null)
            return;

        Nd4j.getExecutioner().commit();

        int numDevices = Nd4j.getAffinityManager().getNumberOfDevices();
        for (int i = 0; i < numDevices; i++) {
            // if current thread equal to this device - we just save it, without duplication
            if (Nd4j.getAffinityManager().getDeviceForCurrentThread() == i) {
                set(i, array);
            } else {
                set(i, Nd4j.getAffinityManager().replicateToDevice(i, array));
            }

        }
    }

This method duplicates array, and stores it to all devices

@param array

This method duplicates array and stores it to all devices


@Override
    public void processMessage() {
        VectorAggregation aggregation = new VectorAggregation(rowIndex, (short) voidConfiguration.getNumberOfShards(),
                        shardIndex, storage.getArray(key).getRow(rowIndex).dup());
        aggregation.setOriginatorId(this.getOriginatorId());
        transport.sendMessage(aggregation);
    }

@ Override public void processMessage ( ) { VectorAggregation aggregation = new VectorAggregation ( rowIndex , ( short ) voidConfiguration . getNumberOfShards ( ) , shardIndex , storage . getArray ( key ) . getRow ( rowIndex ) . dup ( ) ) ; aggregation . setOriginatorId ( this . getOriginatorId ( ) ) ; transport . sendMessage ( aggregation ) ; }

This method will be started in context of executor, either Shard, Client or Backup node

This method will be started in context of executor either Shard Client or Backup node


static public BigDecimal gamma(MathContext mc) {
        /* look it up if possible */
        if (mc.getPrecision() < GAMMA.precision()) {
            return GAMMA.round(mc);
        } else {
            double eps = prec2err(0.577, mc.getPrecision());
            /* Euler-Stieltjes as shown in Dilcher, Aequat Math 48 (1) (1994) 55-85
            14
             */
            MathContext mcloc = new MathContext(2 + mc.getPrecision());
            BigDecimal resul = BigDecimal.ONE;
            resul = resul.add(log(2, mcloc));
            resul = resul.subtract(log(3, mcloc));
            /* how many terms: zeta-1 falls as 1/2^(2n+1), so the
             * terms drop faster than 1/2^(4n+2). Set 1/2^(4kmax+2) < eps.
             * Leading term zeta(3)/(4^1*3) is 0.017. Leading zeta(3) is 1.2. Log(2) is 0.7
             */
            int kmax = (int) ((Math.log(eps / 0.7) - 2.) / 4.);
            mcloc = new MathContext(1 + err2prec(1.2, eps / kmax));
            for (int n = 1;; n++) {
                /* zeta is close to 1. Division of zeta-1 through
                 * 4^n*(2n+1) means divion through roughly 2^(2n+1)
                 */
                BigDecimal c = zeta(2 * n + 1, mcloc).subtract(BigDecimal.ONE);
                BigInteger fourn = BigInteger.valueOf(2 * n + 1);
                fourn = fourn.shiftLeft(2 * n);
                c = divideRound(c, fourn);
                resul = resul.subtract(c);
                if (c.doubleValue() < 0.1 * eps) {
                    break;
                }
            }
            return resul.round(mc);
        }
    }

Euler-Mascheroni constant.

@param mc The required precision of the result.
@return 0.577...


static public BigDecimal sqrt(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            throw new ArithmeticException("negative argument " + x.toString() + " of square root");
        }
        return root(2, x);
    }

static
public
BigDecimal
sqrt
(
final
BigDecimal
x
)
{
if
(
x
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
)
{
throw
new
ArithmeticException
(
"negative argument "
+
x
.
toString
(
)
+
" of square root"
)
;
}
return
root
(
2
,
x
)
;
}

The square root.

@param x the non-negative argument.
@return the square root of the BigDecimal rounded to the precision implied by x.


static public BigDecimal cbrt(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return root(3, x.negate()).negate();
        } else {
            return root(3, x);
        }
    }

static public BigDecimal cbrt ( final BigDecimal x ) { if ( x . compareTo ( BigDecimal . ZERO ) < 0 ) { return root ( 3 , x . negate ( ) ) . negate ( ) ; } else { return root ( 3 , x ) ; } }

The cube root.

@param x The argument.
@return The cubic root of the BigDecimal rounded to the precision implied by x.
The sign of the result is the sign of the argument.


static public BigDecimal root(final int n, final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            throw new ArithmeticException("negative argument " + x.toString() + " of root");
        }
        if (n <= 0) {
            throw new ArithmeticException("negative power " + n + " of root");
        }
        if (n == 1) {
            return x;
        }
        /* start the computation from a double precision estimate */
        BigDecimal s = new BigDecimal(Math.pow(x.doubleValue(), 1.0 / n));
        /* this creates nth with nominal precision of 1 digit
         */
        final BigDecimal nth = new BigDecimal(n);
        /* Specify an internal accuracy within the loop which is
         * slightly larger than what is demanded by ’eps’ below.
         */
        final BigDecimal xhighpr = scalePrec(x, 2);
        MathContext mc = new MathContext(2 + x.precision());
        /* Relative accuracy of the result is eps.
         */
        final double eps = x.ulp().doubleValue() / (2 * n * x.doubleValue());
        for (;;) {
            /* s = s -(s/n-x/n/s^(n-1)) = s-(s-x/s^(n-1))/n; test correction s/n-x/s for being
             * smaller than the precision requested. The relative correction is (1-x/s^n)/n,
             */
            BigDecimal c = xhighpr.divide(s.pow(n - 1), mc);
            c = s.subtract(c);
            MathContext locmc = new MathContext(c.precision());
            c = c.divide(nth, locmc);
            s = s.subtract(c);
            if (Math.abs(c.doubleValue() / s.doubleValue()) < eps) {
                break;
            }
        }
        return s.round(new MathContext(err2prec(eps)));
    }

The integer root.

@param n the positive argument.
@param x the non-negative argument.
@return The n-th root of the BigDecimal rounded to the precision implied by x, x^(1/n).


static public BigDecimal exp(BigDecimal x) {
        /* To calculate the value if x is negative, use exp(-x) = 1/exp(x)
         */
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            final BigDecimal invx = exp(x.negate());
            /* Relative error in inverse of invx is the same as the relative errror in invx.
             * This is used to define the precision of the result.
             */
            MathContext mc = new MathContext(invx.precision());
            return BigDecimal.ONE.divide(invx, mc);
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            /* recover the valid number of digits from x.ulp(), if x hits the
             * zero. The x.precision() is 1 then, and does not provide this information.
             */
            return scalePrec(BigDecimal.ONE, -(int) (Math.log10(x.ulp().doubleValue())));
        } else {
            /* Push the number in the Taylor expansion down to a small
             * value where TAYLOR_NTERM terms will do. If x<1, the n-th term is of the order
             * x^n/n!, and equal to both the absolute and relative error of the result
             * since the result is close to 1. The x.ulp() sets the relative and absolute error
             * of the result, as estimated from the first Taylor term.
             * We want x^TAYLOR_NTERM/TAYLOR_NTERM! < x.ulp, which is guaranteed if
             * x^TAYLOR_NTERM < TAYLOR_NTERM*(TAYLOR_NTERM-1)*...*x.ulp.
             */
            final double xDbl = x.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue();
            if (Math.pow(xDbl, TAYLOR_NTERM) < TAYLOR_NTERM * (TAYLOR_NTERM - 1.0) * (TAYLOR_NTERM - 2.0) * xUlpDbl) {
                /* Add TAYLOR_NTERM terms of the Taylor expansion (Euler’s sum formula)
                 */
                BigDecimal resul = BigDecimal.ONE;
                /* x^i */
                BigDecimal xpowi = BigDecimal.ONE;
                /* i factorial */
                BigInteger ifac = BigInteger.ONE;
                /* TAYLOR_NTERM terms to be added means we move x.ulp() to the right
                 * for each power of 10 in TAYLOR_NTERM, so the addition won’t add noise beyond
                 * what’s already in x.
                 */
                MathContext mcTay = new MathContext(err2prec(1., xUlpDbl / TAYLOR_NTERM));
                for (int i = 1; i <= TAYLOR_NTERM; i++) {
                    ifac = ifac.multiply(BigInteger.valueOf(i));
                    xpowi = xpowi.multiply(x);
                    final BigDecimal c = xpowi.divide(new BigDecimal(ifac), mcTay);
                    resul = resul.add(c);
                    if (Math.abs(xpowi.doubleValue()) < i && Math.abs(c.doubleValue()) < 0.5 * xUlpDbl) {
                        break;
                    }
                }
                /* exp(x+deltax) = exp(x)(1+deltax) if deltax is <<1. So the relative error
                 * in the result equals the absolute error in the argument.
                 */
                MathContext mc = new MathContext(err2prec(xUlpDbl / 2.));
                return resul.round(mc);
            } else {
                /* Compute exp(x) = (exp(0.1*x))^10. Division by 10 does not lead
                 * to loss of accuracy.
                 */
                int exSc = (int) (1.0 - Math.log10(TAYLOR_NTERM * (TAYLOR_NTERM - 1.0) * (TAYLOR_NTERM - 2.0) * xUlpDbl
                                / Math.pow(xDbl, TAYLOR_NTERM)) / (TAYLOR_NTERM - 1.0));
                BigDecimal xby10 = x.scaleByPowerOfTen(-exSc);
                BigDecimal expxby10 = exp(xby10);
                /* Final powering by 10 means that the relative error of the result
                 * is 10 times the relative error of the base (First order binomial expansion).
                 * This looses one digit.
                 */
                MathContext mc = new MathContext(expxby10.precision() - exSc);
                /* Rescaling the powers of 10 is done in chunks of a maximum of 8 to avoid an invalid operation
                17
                 * response by the BigDecimal.pow library or integer overflow.
                 */
                while (exSc > 0) {
                    int exsub = Math.min(8, exSc);
                    exSc -= exsub;
                    MathContext mctmp = new MathContext(expxby10.precision() - exsub + 2);
                    int pex = 1;
                    while (exsub-- > 0) {
                        pex *= 10;
                    }
                    expxby10 = expxby10.pow(pex, mctmp);
                }
                return expxby10.round(mc);
            }
        }
    }

The exponential function.

@param x the argument.
@return exp(x).
The precision of the result is implicitly defined by the precision in the argument.
16
In particular this means that "Invalid Operation" errors are thrown if catastrophic
cancellation of digits causes the result to have no valid digits left.


static public BigDecimal exp(final MathContext mc) {
        /* look it up if possible */
        if (mc.getPrecision() < E.precision()) {
            return E.round(mc);
        } else {
            /* Instantiate a 1.0 with the requested pseudo-accuracy
             * and delegate the computation to the public method above.
             */
            BigDecimal uni = scalePrec(BigDecimal.ONE, mc.getPrecision());
            return exp(uni);
        }
    }

The base of the natural logarithm.

@param mc the required precision of the result
@return exp(1) = 2.71828....


static public BigDecimal pow(final BigDecimal x, final BigDecimal y) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            throw new ArithmeticException("Cannot power negative " + x.toString());
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            /* return x^y = exp(y*log(x)) ;
             */
            BigDecimal logx = log(x);
            BigDecimal ylogx = y.multiply(logx);
            BigDecimal resul = exp(ylogx);
            /* The estimation of the relative error in the result is |log(x)*err(y)|+|y*err(x)/x|
             */
            double errR = Math.abs(logx.doubleValue() * y.ulp().doubleValue() / 2.)
                            + Math.abs(y.doubleValue() * x.ulp().doubleValue() / 2. / x.doubleValue());
            MathContext mcR = new MathContext(err2prec(1.0, errR));
            return resul.round(mcR);
        }
    }

/* return x^y = exp(y*log(x)) ;
             */

Power function.

@param x Base of the power.
@param y Exponent of the power.
@return x^y.
The estimation of the relative error in the result is |log(x)*err(y)|+|y*err(x)/x|


static public BigDecimal powRound(final BigDecimal x, final int n) {
        /* The relative error in the result is n times the relative error in the input.
         * The estimation is slightly optimistic due to the integer rounding of the logarithm.
         */
        MathContext mc = new MathContext(x.precision() - (int) Math.log10((double) (Math.abs(n))));
        return x.pow(n, mc);
    }

Raise to an integer power and round.

@param x The base.
@param n The exponent.
@return x^n.


static public BigDecimal sin(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return sin(x.negate()).negate();
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            /* reduce modulo 2pi
             */
            BigDecimal res = mod2pi(x);
            double errpi = 0.5 * Math.abs(x.ulp().doubleValue());
            int val = 2 + err2prec(FastMath.PI, errpi);
            MathContext mc = new MathContext(val);
            BigDecimal p = pi(mc);
            mc = new MathContext(x.precision());
            if (res.compareTo(p) > 0) {
                /* pi<x<=2pi: sin(x)= - sin(x-pi)
                 */
                return sin(subtractRound(res, p)).negate();
            } else if (res.multiply(new BigDecimal(2)).compareTo(p) > 0) {
                /* pi/2<x<=pi: sin(x)= sin(pi-x)
                 */
                return sin(subtractRound(p, res));
            } else {
                /* for the range 0<=x<Pi/2 one could use sin(2x)=2sin(x)cos(x)
                 * to split this further. Here, use the sine up to pi/4 and the cosine higher up.
                 */
                if (res.multiply(new BigDecimal(4)).compareTo(p) > 0) {
                    /* x>pi/4: sin(x) = cos(pi/2-x)
                     */
                    return cos(subtractRound(p.divide(new BigDecimal(2)), res));
                } else {
                    /* Simple Taylor expansion, sum_{i=1..infinity} (-1)^(..)res^(2i+1)/(2i+1)! */
                    BigDecimal resul = res;
                    /* x^i */
                    BigDecimal xpowi = res;
                    /* 2i+1 factorial */
                    BigInteger ifac = BigInteger.ONE;
                    /* The error in the result is set by the error in x itself.
                     */
                    double xUlpDbl = res.ulp().doubleValue();
                    /* The error in the result is set by the error in x itself.
                     * We need at most k terms to squeeze x^(2k+1)/(2k+1)! below this value.
                     * x^(2k+1) < x.ulp; (2k+1)*log10(x) < -x.precision; 2k*log10(x)< -x.precision;
                     * 2k*(-log10(x)) > x.precision; 2k*log10(1/x) > x.precision
                     */
                    int k = (int) (res.precision() / Math.log10(1.0 / res.doubleValue())) / 2;
                    MathContext mcTay = new MathContext(err2prec(res.doubleValue(), xUlpDbl / k));
                    for (int i = 1;; i++) {
                        /* TBD: at which precision will 2*i or 2*i+1 overflow?
                         */
                        ifac = ifac.multiply(BigInteger.valueOf(2 * i));
                        ifac = ifac.multiply(BigInteger.valueOf(2 * i + 1));
                        xpowi = xpowi.multiply(res).multiply(res).negate();
                        BigDecimal corr = xpowi.divide(new BigDecimal(ifac), mcTay);
                        resul = resul.add(corr);
                        if (corr.abs().doubleValue() < 0.5 * xUlpDbl) {
                            break;
                        }
                    }
                    /* The error in the result is set by the error in x itself.
                     */
                    mc = new MathContext(res.precision());
                    return resul.round(mc);
                }
            }
        } /* sin */
    }

Trigonometric sine.

@param x The argument in radians.
@return sin(x) in the range -1 to 1.


static public BigDecimal tan(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else if (x.compareTo(BigDecimal.ZERO) < 0) {
            return tan(x.negate()).negate();
        } else {
            /* reduce modulo pi
             */
            BigDecimal res = modpi(x);
            /* absolute error in the result is err(x)/cos^2(x) to lowest order
             */
            final double xDbl = res.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue() / 2.;
            final double eps = xUlpDbl / 2. / Math.pow(Math.cos(xDbl), 2.);
            if (xDbl > 0.8) {
                /* tan(x) = 1/cot(x) */
                BigDecimal co = cot(x);
                MathContext mc = new MathContext(err2prec(1. / co.doubleValue(), eps));
                return BigDecimal.ONE.divide(co, mc);
            } else {
                final BigDecimal xhighpr = scalePrec(res, 2);
                final BigDecimal xhighprSq = multiplyRound(xhighpr, xhighpr);
                BigDecimal result = xhighpr.plus();
                /* x^(2i+1) */
                BigDecimal xpowi = xhighpr;
                Bernoulli b = new Bernoulli();
                /* 2^(2i) */
                BigInteger fourn = BigInteger.valueOf(4);
                /* (2i)! */
                BigInteger fac = BigInteger.valueOf(2);
                for (int i = 2;; i++) {
                    Rational f = b.at(2 * i).abs();
                    fourn = fourn.shiftLeft(2);
                    fac = fac.multiply(BigInteger.valueOf(2 * i)).multiply(BigInteger.valueOf(2 * i - 1));
                    f = f.multiply(fourn).multiply(fourn.subtract(BigInteger.ONE)).divide(fac);
                    xpowi = multiplyRound(xpowi, xhighprSq);
                    BigDecimal c = multiplyRound(xpowi, f);
                    result = result.add(c);
                    if (Math.abs(c.doubleValue()) < 0.1 * eps) {
                        break;
                    }
                }
                MathContext mc = new MathContext(err2prec(result.doubleValue(), eps));
                return result.round(mc);
            }
        }
    }

The trigonometric tangent.

@param x the argument in radians.
@return the tan(x)


static public BigDecimal cosh(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return cos(x.negate());
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ONE;
        } else {
            if (x.doubleValue() > 1.5) {
                /* cosh^2(x) = 1+ sinh^2(x).
                 */
                return hypot(1, sinh(x));

            } else {
                BigDecimal xhighpr = scalePrec(x, 2);
                /* Simple Taylor expansion, sum_{0=1..infinity} x^(2i)/(2i)! */
                BigDecimal resul = BigDecimal.ONE;
                /* x^i */
                BigDecimal xpowi = BigDecimal.ONE;
                /* 2i factorial */
                BigInteger ifac = BigInteger.ONE;
                /* The absolute error in the result is the error in x^2/2 which is x times the error in x.
                 */

                double xUlpDbl = 0.5 * x.ulp().doubleValue() * x.doubleValue();
                /* The error in the result is set by the error in x^2/2 itself, xUlpDbl.
                 * We need at most k terms to push x^(2k)/(2k)! below this value.
                 * x^(2k) < xUlpDbl; (2k)*log(x) < log(xUlpDbl);
                 */

                int k = (int) (Math.log(xUlpDbl) / Math.log(x.doubleValue())) / 2;
                /* The individual terms are all smaller than 1, so an estimate of 1.0 for
                 * the absolute value will give a safe relative error estimate for the indivdual terms
                 */
                MathContext mcTay = new MathContext(err2prec(1., xUlpDbl / k));

                for (int i = 1;; i++) {
                    /* TBD: at which precision will 2*i-1 or 2*i overflow?
                     */
                    ifac = ifac.multiply(BigInteger.valueOf(2 * i - 1));
                    ifac = ifac.multiply(BigInteger.valueOf(2 * i));
                    xpowi = xpowi.multiply(xhighpr).multiply(xhighpr);
                    BigDecimal corr = xpowi.divide(new BigDecimal(ifac), mcTay);
                    resul = resul.add(corr);

                    if (corr.abs().doubleValue() < 0.5 * xUlpDbl) {
                        break;
                    }

                } /* The error in the result is governed by the error in x itself.
                  */
                MathContext mc = new MathContext(err2prec(resul.doubleValue(), xUlpDbl));

                return resul.round(mc);

            }
        }
    }

The hyperbolic cosine.

@param x The argument.
@return The cosh(x) = (exp(x)+exp(-x))/2 .


static public BigDecimal sinh(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return sinh(x.negate()).negate();
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            if (x.doubleValue() > 2.4) {
                /* Move closer to zero with sinh(2x)= 2*sinh(x)*cosh(x).
                 */
                BigDecimal two = new BigDecimal(2);
                BigDecimal xhalf = x.divide(two);

                BigDecimal resul = sinh(xhalf).multiply(cosh(xhalf)).multiply(two);
                /* The error in the result is set by the error in x itself.
                 * The first derivative of sinh(x) is cosh(x), so the absolute error
                 * in the result is cosh(x)*errx, and the relative error is coth(x)*errx = errx/tanh(x)
                 */

                double eps = Math.tanh(x.doubleValue());
                MathContext mc = new MathContext(err2prec(0.5 * x.ulp().doubleValue() / eps));

                return resul.round(mc);

            } else {
                BigDecimal xhighpr = scalePrec(x, 2);
                /* Simple Taylor expansion, sum_{i=0..infinity} x^(2i+1)/(2i+1)! */
                BigDecimal resul = xhighpr;
                /* x^i */
                BigDecimal xpowi = xhighpr;
                /* 2i+1 factorial */
                BigInteger ifac = BigInteger.ONE;
                /* The error in the result is set by the error in x itself.
                 */

                double xUlpDbl = x.ulp().doubleValue();
                /* The error in the result is set by the error in x itself.
                 * We need at most k terms to squeeze x^(2k+1)/(2k+1)! below this value.
                 * x^(2k+1) < x.ulp; (2k+1)*log10(x) < -x.precision; 2k*log10(x)< -x.precision;
                 * 2k*(-log10(x)) > x.precision; 2k*log10(1/x) > x.precision
                 */

                int k = (int) (x.precision() / Math.log10(1.0 / xhighpr.doubleValue())) / 2;
                MathContext mcTay = new MathContext(err2prec(x.doubleValue(), xUlpDbl / k));

                for (int i = 1;; i++) {
                    /* TBD: at which precision will 2*i or 2*i+1 overflow?
                     */
                    ifac = ifac.multiply(BigInteger.valueOf(2 * i));
                    ifac = ifac.multiply(BigInteger.valueOf(2 * i + 1));
                    xpowi = xpowi.multiply(xhighpr).multiply(xhighpr);
                    BigDecimal corr = xpowi.divide(new BigDecimal(ifac), mcTay);
                    resul = resul.add(corr);

                    if (corr.abs().doubleValue() < 0.5 * xUlpDbl) {
                        break;
                    }

                } /* The error in the result is set by the error in x itself.
                  */
                MathContext mc = new MathContext(x.precision());

                return resul.round(mc);

            }
        }
    }

The hyperbolic sine.

@param x the argument.
@return the sinh(x) = (exp(x)-exp(-x))/2 .


static public BigDecimal tanh(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return tanh(x.negate()).negate();
        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            BigDecimal xhighpr = scalePrec(x, 2);
            /* tanh(x) = (1-e^(-2x))/(1+e^(-2x)) .
             */
            BigDecimal exp2x = exp(xhighpr.multiply(new BigDecimal(-2)));
            /* The error in tanh x is err(x)/cosh^2(x).
             */

            double eps = 0.5 * x.ulp().doubleValue() / Math.pow(Math.cosh(x.doubleValue()), 2.0);
            MathContext mc = new MathContext(err2prec(Math.tanh(x.doubleValue()), eps));

            return BigDecimal.ONE.subtract(exp2x).divide(BigDecimal.ONE.add(exp2x), mc);

        }
    }

The hyperbolic tangent.

@param x The argument.
@return The tanh(x) = sinh(x)/cosh(x).


static public BigDecimal asinh(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            BigDecimal xhighpr = scalePrec(x, 2);
            /* arcsinh(x) = log(x+hypot(1,x))
             */
            BigDecimal logx = log(hypot(1, xhighpr).add(xhighpr));
            /* The absolute error in arcsinh x is err(x)/sqrt(1+x^2)
             */

            double xDbl = x.doubleValue();

            double eps = 0.5 * x.ulp().doubleValue() / Math.hypot(1., xDbl);
            MathContext mc = new MathContext(err2prec(logx.doubleValue(), eps));

            return logx.round(mc);

        }
    }

/* arcsinh(x) = log(x+hypot(1,x))
             */

The inverse hyperbolic sine.

@param x The argument.
@return The arcsinh(x) .


static public BigDecimal acosh(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ONE) < 0) {
            throw new ArithmeticException("Out of range argument cosh " + x.toString());
        } else if (x.compareTo(BigDecimal.ONE) == 0) {
            return BigDecimal.ZERO;
        } else {
            BigDecimal xhighpr = scalePrec(x, 2);
            /* arccosh(x) = log(x+sqrt(x^2-1))
             */
            BigDecimal logx = log(sqrt(xhighpr.pow(2).subtract(BigDecimal.ONE)).add(xhighpr));
            /* The absolute error in arcsinh x is err(x)/sqrt(x^2-1)
             */

            double xDbl = x.doubleValue();

            double eps = 0.5 * x.ulp().doubleValue() / Math.sqrt(xDbl * xDbl - 1.);
            MathContext mc = new MathContext(err2prec(logx.doubleValue(), eps));

            return logx.round(mc);

        }
    }

/* arccosh(x) = log(x+sqrt(x^2-1))
             */

The inverse hyperbolic cosine.

@param x The argument.
@return The arccosh(x) .


static public BigDecimal Gamma(final BigDecimal x) {
        /* reduce to interval near 1.0 with the functional relation, Abramowitz-Stegun 6.1.33
         */
        if (x.compareTo(BigDecimal.ZERO) < 0) {
            return divideRound(Gamma(x.add(BigDecimal.ONE)), x);
        } else if (x.doubleValue() > 1.5) {
            /* Gamma(x) = Gamma(xmin+n) = Gamma(xmin)*Pochhammer(xmin,n).
             */
            int n = (int) (x.doubleValue() - 0.5);
            BigDecimal xmin1 = x.subtract(new BigDecimal(n));

            return multiplyRound(Gamma(xmin1), pochhammer(xmin1, n));

        } else {
            /* apply Abramowitz-Stegun 6.1.33
             */
            BigDecimal z = x.subtract(BigDecimal.ONE);
            /* add intermediately 2 digits to the partial sum accumulation
             */
            z = scalePrec(z, 2);
            MathContext mcloc = new MathContext(z.precision());
            /* measure of the absolute error is the relative error in the first, logarithmic term
             */

            double eps = x.ulp().doubleValue() / x.doubleValue();
            BigDecimal resul = log(scalePrec(x, 2)).negate();

            if (x.compareTo(BigDecimal.ONE) != 0) {
                BigDecimal gammCompl = BigDecimal.ONE.subtract(gamma(mcloc));
                resul = resul.add(multiplyRound(z, gammCompl));

                for (int n = 2;; n++) {
                    /* multiplying z^n/n by zeta(n-1) means that the two relative errors add.
                     * so the requirement in the relative error of zeta(n)-1 is that this is somewhat
                     * smaller than the relative error in z^n/n (the absolute error of thelatter is the
                     * absolute error in z)
                     */
                    BigDecimal c = divideRound(z.pow(n, mcloc), n);
                    MathContext m = new MathContext(err2prec(n * z.ulp().doubleValue() / 2. / z.doubleValue()));
                    c = c.round(m);
                    /* At larger n, zeta(n)-1 is roughly 1/2^n. The product is c/2^n.
                     * The relative error in c is c.ulp/2/c . The error in the product should be small versus eps/10.
                     * Error from 1/2^n is c*err(sigma-1).
                     * We need a relative error of zeta-1 of the order of c.ulp/50/c. This is an absolute
                     * error in zeta-1 of c.ulp/50/c/2^n, and also the absolute error in zeta, because zeta is
                     * of the order of 1.
                     */

                    if (eps / 100. / c.doubleValue() < 0.01) {
                        m = new MathContext(err2prec(eps / 100. / c.doubleValue()));
                    } else {
                        m = new MathContext(2);
                    }
                    /* zeta(n) -1 */
                    BigDecimal zetm1 = zeta(n, m).subtract(BigDecimal.ONE);
                    c = multiplyRound(c, zetm1);

                    if (n % 2 == 0) {
                        resul = resul.add(c);
                    } else {
                        resul = resul.subtract(c);
                    }
                    /* alternating sum, so truncating as eps is reached suffices
                     */

                    if (Math.abs(c.doubleValue()) < eps) {
                        break;
                    }

                }
            }
            /* The relative error in the result is the absolute error in the
             * input variable times the digamma (psi) value at that point.
             */
            double psi = 0.5772156649;

            double zdbl = z.doubleValue();

            for (int n = 1; n < 5; n++) {
                psi += zdbl / n / (n + zdbl);
            }
            eps = psi * x.ulp().doubleValue() / 2.;
            mcloc = new MathContext(err2prec(eps));

            return exp(resul).round(mcloc);

        }
    }

/* apply Abramowitz-Stegun 6.1.33
             */

The Gamma function.

@param x The argument.
@return Gamma(x).


static protected BigDecimal broadhurstBBP(final int n, final int p, final int a[], MathContext mc) {
        /* Explore the actual magnitude of the result first with a quick estimate.
        */
        double x = 0.0;

        for (int k = 1; k < 10; k++) {
            x += a[(k - 1) % 8] / Math.pow(2., p * (k + 1) / 2) / Math.pow((double) k, n);
        }
        /* Convert the relative precision and estimate of the result into an absolute precision.
         */

        double eps = prec2err(x, mc.getPrecision());
        /* Divide this through the number of terms in the sum to account for error accumulation
         * The divisor 2^(p(k+1)/2) means that on the average each 8th term in k has shrunk by
         * relative to the 8th predecessor by 1/2^(4p). 1/2^(4pc) = 10^(-precision) with c the 8term
         * cycles yields c=log_2( 10^precision)/4p = 3.3*precision/4p with k=8c
         */

        int kmax = (int) (6.6 * mc.getPrecision() / p);
        /* Now eps is the absolute error in each term */
        eps /= kmax;
        BigDecimal res = BigDecimal.ZERO;

        for (int c = 0;; c++) {
            Rational r = new Rational();

            for (int k = 0; k < 8; k++) {
                Rational tmp = new Rational(BigInteger.valueOf(a[k]), BigInteger.valueOf((1 + 8 * c + k)).pow(n));
                /* floor( (pk+p)/2)
                 */

                int pk1h = p * (2 + 8 * c + k) / 2;
                tmp = tmp.divide(BigInteger.ONE.shiftLeft(pk1h));
                r = r.add(tmp);

            }
            if (Math.abs(r.doubleValue()) < eps) {
                break;
            }
            MathContext mcloc = new MathContext(1 + err2prec(r.doubleValue(), eps));
            res = res.add(r.BigDecimalValue(mcloc));

        }
        return res.round(mc);

    }

Broadhurst ladder sequence.

@param a  The vector of 8 integer arguments
@param mc Specification of the accuracy of the result
@return S_(n, p)(a)
@see \protect\vrule width0pt\protect\href{http://arxiv.org/abs/math/9803067}{arXiv:math/9803067}


static public BigDecimal scalePrec(final BigDecimal x, int d) {
        return x.setScale(d + x.scale());

    }

static public BigDecimal scalePrec ( final BigDecimal x , int d ) { return x . setScale ( d + x . scale ( ) ) ; }

Append decimal zeros to the value. This returns a value which appears to have
a higher precision than the input.

@param x The input value
@param d The (positive) value of zeros to be added as least significant digits.
@return The same value as the input but with increased (pseudo) precision.

Append decimal zeros to the value . This returns a value which appears to have a higher precision than the input .


static public BigDecimal scalePrec(final BigDecimal x, final MathContext mc) {
        final int diffPr = mc.getPrecision() - x.precision();

        if (diffPr > 0) {
            return scalePrec(x, diffPr);
        } else {
            return x;
        }

    }

static public BigDecimal scalePrec ( final BigDecimal x , final MathContext mc ) { final int diffPr = mc . getPrecision ( ) - x . precision ( ) ; if ( diffPr > 0 ) { return scalePrec ( x , diffPr ) ; } else { return x ; } }

Boost the precision by appending decimal zeros to the value. This returns a value which appears to have
a higher precision than the input.

@param x  The input value
@param mc The requirement on the minimum precision on return.
@return The same value as the input but with increased (pseudo) precision.

Boost the precision by appending decimal zeros to the value . This returns a value which appears to have a higher precision than the input .


static public int err2prec(BigDecimal x, BigDecimal xerr) {
        return err2prec(xerr.divide(x, MathContext.DECIMAL64).doubleValue());

    }

static public int err2prec ( BigDecimal x , BigDecimal xerr ) { return err2prec ( xerr . divide ( x , MathContext . DECIMAL64 ) . doubleValue ( ) ) ; }

Convert an absolute error to a precision.

@param x    The value of the variable
@param xerr The absolute error in the variable
@return The number of valid digits in x.
The value is rounded down, and on the pessimistic side for that reason.

Convert an absolute error to a precision .


public void putFunctionForId(String id, DifferentialFunction function) {
        if (functionInstancesById.containsKey(id)) {
            throw new ND4JIllegalStateException("Function by id already exists!");
        } else if (function instanceof SDVariable) {
            throw new ND4JIllegalStateException("Function must not be a variable!");
        }

        functionInstancesById.put(id, function);
    }

public
void
putFunctionForId
(
String
id
,
DifferentialFunction
function
)
{
if
(
functionInstancesById
.
containsKey
(
id
)
)
{
throw
new
ND4JIllegalStateException
(
"Function by id already exists!"
)
;
}
else
if
(
function
instanceof
SDVariable
)
{
throw
new
ND4JIllegalStateException
(
"Function must not be a variable!"
)
;
}
functionInstancesById
.
put
(
id
,
function
)
;
}

Put the function for id

@param id       the id
@param function the function


public String[] getInputsForFunction(DifferentialFunction function) {
        if (!incomingArgsReverse.containsKey(function.getOwnName()))
            throw new ND4JIllegalStateException("Illegal function instance id found " + function.getOwnName());
        return incomingArgsReverse.get(function.getOwnName());
    }

public
String
[
]
getInputsForFunction
(
DifferentialFunction
function
)
{
if
(
!
incomingArgsReverse
.
containsKey
(
function
.
getOwnName
(
)
)
)
throw
new
ND4JIllegalStateException
(
"Illegal function instance id found "
+
function
.
getOwnName
(
)
)
;
return
incomingArgsReverse
.
get
(
function
.
getOwnName
(
)
)
;
}

Returns the inputs for the given function

@param function the function to get the
inputs for
@return the input ids for a given function


public void updateArrayForVarName(String varName, INDArray arr) {
        if (!variableNameToArr.containsKey(varName)) {
            throw new ND4JIllegalStateException("Array for " + varName + " does not exist. Please use putArrayForVertexId instead.");
        }

        variableNameToArr.put(varName, arr);
        reverseArrayLookup.put(arr, getVariable(varName));
    }

Update the ndarray for the given vertex id.

@param varName
@param arr
@throws {@link ND4JIllegalStateException} when the array does not exist.

Update the ndarray for the given vertex id .