public void putShapeForVarName(String varName, long[] shape) {
        if (shape == null) {
            throw new ND4JIllegalStateException("Shape must not be null!");
        }

        if (variableNameToShape.containsKey(varName)) {
            throw new ND4JIllegalStateException("Shape for " + varName + " already exists!");
        }

        for (int i = 0; i < shape.length; i++) {
            if (shape[i] < 1) {
                addAsPlaceHolder(varName);
                placeHolderOriginalShapes.put(varName, shape);
                return;
            }
        }

        variableNameToShape.put(varName, shape);
    }

public
void
putShapeForVarName
(
String
varName
,
long
[
]
shape
)
{
if
(
shape
==
)
{
throw
new
ND4JIllegalStateException
(
"Shape must not be null!"
)
;
}
if
(
variableNameToShape
.
containsKey
(
varName
)
)
{
throw
new
ND4JIllegalStateException
(
"Shape for "
+
varName
+
" already exists!"
)
;
}
for
(
int
i
=
0
;
i
<
shape
.
length
;
i
++
)
{
if
(
shape
[
i
]
<
1
)
{
addAsPlaceHolder
(
varName
)
;
placeHolderOriginalShapes
.
put
(
varName
,
shape
)
;
return
;
}
}
variableNameToShape
.
put
(
varName
,
shape
)
;
}

Associate a vertex id with the given shape.

@param varName the vertex id to associate
@param shape   the shape to associate with

Associate a vertex id with the given shape .


public void associateArrayWithVariable(INDArray arr, SDVariable variable) {
        if (variable == null) {
            throw new ND4JIllegalArgumentException("Variable must not be null!");
        }

        if (arr == null) {
            throw new ND4JIllegalArgumentException("Array must not be null");
        }

        reverseArrayLookup.put(arr, variable);
        variableNameToArr.put(variable.getVarName(), arr);
        if (!shapeAlreadyExistsForVarName(variable.getVarName()))
            putShapeForVarName(variable.getVarName(), arr.shape());
        else {
            updateShapeForVarName(variable.getVarName(), arr.shape());
        }
    }

public
void
associateArrayWithVariable
(
INDArray
arr
,
SDVariable
variable
)
{
if
(
variable
==
)
{
throw
new
ND4JIllegalArgumentException
(
"Variable must not be null!"
)
;
}
if
(
arr
==
)
{
throw
new
ND4JIllegalArgumentException
(
"Array must not be null"
)
;
}
reverseArrayLookup
.
put
(
arr
,
variable
)
;
variableNameToArr
.
put
(
variable
.
getVarName
(
)
,
arr
)
;
if
(
!
shapeAlreadyExistsForVarName
(
variable
.
getVarName
(
)
)
)
putShapeForVarName
(
variable
.
getVarName
(
)
,
arr
.
shape
(
)
)
;
else
{
updateShapeForVarName
(
variable
.
getVarName
(
)
,
arr
.
shape
(
)
)
;
}
}

Associate the array with the given variable.

@param arr      the array to get the variable for
@param variable the variable to associate

Associate the array with the given variable .


public <T> T getPropertyForFunction(DifferentialFunction functionInstance, String propertyName) {
        if (!propertiesForFunction.containsKey(functionInstance.getOwnName())) {
            return null;
        } else {
            val map = propertiesForFunction.get(functionInstance.getOwnName());
            return (T) map.get(propertyName);

        }
    }

public < T > T getPropertyForFunction ( DifferentialFunction functionInstance , String propertyName ) { if ( ! propertiesForFunction . containsKey ( functionInstance . getOwnName ( ) ) ) { return null ; } else { val map = propertiesForFunction . get ( functionInstance . getOwnName ( ) ) ; return ( T ) map . get ( propertyName ) ; } }

Get the property for a given function

@param functionInstance the function to get the
property for
@param propertyName     the name of the property to get
@param <T>              the inferred return type
@return the property for the given function


public void addPropertyForFunction(DifferentialFunction functionFor, String propertyName, INDArray property) {
        addPropertyForFunction(functionFor, propertyName, (Object) property);
    }

public void addPropertyForFunction ( DifferentialFunction functionFor , String propertyName , INDArray property ) { addPropertyForFunction ( functionFor , propertyName , ( Object ) property ) ; }

Add a property for the given function

@param functionFor  the function add a property for
@param propertyName the property name
@param property     the property value


public void addOutgoingFor(String[] varNames, DifferentialFunction function) {

        if (function.getOwnName() == null)
            throw new ND4JIllegalStateException("Instance id can not be null. Function not initialized properly");

        if (outgoingArgsReverse.containsKey(function.getOwnName())) {
            throw new ND4JIllegalStateException("Outgoing arguments already declared for " + function);
        }

        if (varNames == null)
            throw new ND4JIllegalStateException("Var names can not be null!");

        for (int i = 0; i < varNames.length; i++) {
            if (varNames[i] == null)
                throw new ND4JIllegalStateException("Variable name elements can not be null!");
        }

        outgoingArgsReverse.put(function.getOwnName(), varNames);
        outgoingArgs.put(varNames, function);

        for (val resultName : varNames) {
            List<DifferentialFunction> funcs = functionOutputFor.get(resultName);
            if (funcs == null) {
                funcs = new ArrayList<>();
                functionOutputFor.put(resultName, funcs);
            }

            funcs.add(function);
        }

    }

Adds outgoing arguments to the graph.
Also checks for input arguments
and updates the graph adding an appropriate edge
when the full graph is declared.

@param varNames
@param function

Adds outgoing arguments to the graph . Also checks for input arguments and updates the graph adding an appropriate edge when the full graph is declared .


public void addArgsFor(String[] variables, DifferentialFunction function) {
        if (function.getOwnName() == null)
            throw new ND4JIllegalStateException("Instance id can not be null. Function not initialized properly");

        //double check if function contains placeholder args
        for (val varName : variables) {
            if (isPlaceHolder(varName)) {
                placeHolderFunctions.add(function.getOwnName());
            }
        }

        incomingArgs.put(variables, function);
        incomingArgsReverse.put(function.getOwnName(), variables);
        for (val variableName : variables) {
            List<DifferentialFunction> funcs = functionsArgsFor.get(variableName);
            if (funcs == null) {
                funcs = new ArrayList<>();
                functionsArgsFor.put(variableName, funcs);
            }

            funcs.add(function);
        }

    }

Adds incoming args to the graph

@param variables
@param function


public boolean hasArgs(DifferentialFunction function) {
        val vertexIdArgs = incomingArgsReverse.get(function.getOwnName());
        if (vertexIdArgs != null) {
            val args = incomingArgs.get(vertexIdArgs);
            if (args != null)
                return true;
        }
        return false;
    }

public boolean hasArgs ( DifferentialFunction function ) { val vertexIdArgs = incomingArgsReverse . get ( function . getOwnName ( ) ) ; if ( vertexIdArgs != null ) { val args = incomingArgs . get ( vertexIdArgs ) ; if ( args != null ) return true ; } return false ; }

Returns true if this function already
has defined arguments

@param function the function to check
@return true if the function has args false otherwise


public INDArray[] eval(Map<String, INDArray> inputs) {

        SameDiff execPipeline = dup();

        List<DifferentialFunction> opExecAction = execPipeline.exec().getRight();
        if (opExecAction.isEmpty())
            throw new IllegalStateException("No ops found to execute.");
        INDArray[] ret = new INDArray[opExecAction.size()];
        for (int i = 0; i < ret.length; i++) {
            val varName = opExecAction.get(i).outputVariables()[0].getVarName();
            ret[i] = execPipeline.getArrForVarName(varName);
        }
        return ret;
    }

public
INDArray
[
]
eval
(
Map
<
String
,
INDArray
>
inputs
)
{
SameDiff
execPipeline
=
dup
(
)
;
List
<
DifferentialFunction
>
opExecAction
=
execPipeline
.
exec
(
)
.
getRight
(
)
;
if
(
opExecAction
.
isEmpty
(
)
)
throw
new
IllegalStateException
(
"No ops found to execute."
)
;
INDArray
[
]
ret
=
new
INDArray
[
opExecAction
.
size
(
)
]
;
for
(
int
i
=
0
;
i
<
ret
.
length
;
i
++
)
{
val
varName
=
opExecAction
.
get
(
i
)
.
outputVariables
(
)
[
0
]
.
getVarName
(
)
;
ret
[
i
]
=
execPipeline
.
getArrForVarName
(
varName
)
;
}
return
ret
;
}

Evaluate the given inputs
based on the current graph

@param inputs the inputs to evaluate
@return


public SDVariable one(String name, int[] shape) {
        return var(name, ArrayUtil.toLongArray(shape), new ConstantInitScheme('f', 1.0));
    }

public SDVariable one ( String name , int [ ] shape ) { return var ( name , ArrayUtil . toLongArray ( shape ) , new ConstantInitScheme ( ' ' , 1.0 ) ) ; }

Variable initialization
with 1.0

@param name  the opName of the variable
@param shape the shape of the array to be created
@return the created variable


public SDVariable onesLike(String name, SDVariable input) {
        return f().onesLike(name, input);
    }

public SDVariable onesLike ( String name , SDVariable input ) { return f ( ) . onesLike ( name , input ) ; }

Return a variable of all 1s, with the same shape as the input

@param input
@return

Return a variable of all 1s with the same shape as the input


public SDVariable zerosLike(String name, SDVariable input) {
        return f().zerosLike(name, input);
    }

public SDVariable zerosLike ( String name , SDVariable input ) { return f ( ) . zerosLike ( name , input ) ; }

Return a variable of all 0s, with the same shape as the input

@param input
@return

Return a variable of all 0s with the same shape as the input


public void removeArgFromFunction(String varName, DifferentialFunction function) {
        val args = function.args();

        for (int i = 0; i < args.length; i++) {
            if (args[i].getVarName().equals(varName)) {
                /**
                 * Since we are removing the variable reference
                 * from the arguments we need to  update both
                 * the reverse and forward arguments.
                 */
                val reverseArgs = incomingArgsReverse.get(function.getOwnName());
                incomingArgs.remove(reverseArgs);
                incomingArgsReverse.remove(function.getOwnName());
                val newArgs = new ArrayList<String>(args.length - 1);
                for (int arg = 0; arg < args.length; arg++) {
                    if (!reverseArgs[arg].equals(varName)) {
                        newArgs.add(reverseArgs[arg]);
                    }
                }

                val newArgsArr = newArgs.toArray(new String[newArgs.size()]);
                incomingArgs.put(newArgsArr, function);
                incomingArgsReverse.put(function.getOwnName(), newArgsArr);
                //no further need to scan
                break;
            }
        }

    }

Remove an argument for a function. Note that if this function
does not contain the argument, it will just be a no op.

@param varName  the variable name to remove
@param function the function to remove the argument from

Remove an argument for a function . Note that if this function does not contain the argument it will just be a no op .


public void setGradientForVariableName(String variableName, SDVariable variable) {
        if (variable == null) {
            throw new ND4JIllegalStateException("Unable to set null gradient for variable name " + variableName);
        }

        gradients.put(variableName, variable);
    }

Assign a vertex id
to a gradient

@param variableName the vertex id
to assign
@param variable     the variable


public SDVariable avgPooling3d(SDVariable[] inputs, Pooling3DConfig pooling3DConfig) {
        return avgPooling3d(null, inputs, pooling3DConfig);
    }

public SDVariable avgPooling3d ( SDVariable [ ] inputs , Pooling3DConfig pooling3DConfig ) { return avgPooling3d ( null , inputs , pooling3DConfig ) ; }

Average pooling 3d operation.

@param inputs       the inputs to average pooling 3d
@param pooling3DConfig the configuration
@return


public SDVariable gru(String baseName, GRUCellConfiguration configuration) {
        return new GRUCell(this, configuration).outputVariables(baseName)[0];
    }

public SDVariable gru ( String baseName , GRUCellConfiguration configuration ) { return new GRUCell ( this , configuration ) . outputVariables ( baseName ) [ 0 ] ; }

The gru cell

@param baseName      the base name for the gru cell
@param configuration teh configuration to use
@return


public List<DifferentialFunction> exec(List<DifferentialFunction> ops) {
        for (int i = 0; i < ops.size(); i++) {
            Op op = (Op) ops.get(i);
            Nd4j.getExecutioner().exec(op);
        }
        return ops;
    }

public List < DifferentialFunction > exec ( List < DifferentialFunction > ops ) { for ( int i = 0 ; i < ops . size ( ) ; i ++ ) { Op op = ( Op ) ops . get ( i ) ; Nd4j . getExecutioner ( ) . exec ( op ) ; } return ops ; }

Executes the list of operations.
This exec method is for
only invoking operations
rather than creating them

@param ops the list of already created ops
@return the passes in list

Executes the list of operations . This exec method is for only invoking operations rather than creating them


public While whileStatement(SameDiffConditional sameDiffConditional,
                                SameDiffFunctionDefinition conditionBody,
                                SameDiff.SameDiffFunctionDefinition loopBody
            , SDVariable[] inputVars) {
        return While.builder()
                .inputVars(inputVars)
                .condition(conditionBody)
                .predicate(sameDiffConditional)
                .trueBody(loopBody)
                .parent(this)
                .blockName("while-" + UUID.randomUUID().toString())
                .build();
    }

public While whileStatement ( SameDiffConditional sameDiffConditional , SameDiffFunctionDefinition conditionBody , SameDiff . SameDiffFunctionDefinition loopBody , SDVariable [ ] inputVars ) { return While . builder ( ) . inputVars ( inputVars ) . condition ( conditionBody ) . predicate ( sameDiffConditional ) . trueBody ( loopBody ) . parent ( this ) . blockName ( "while-" + UUID . randomUUID ( ) . toString ( ) ) . build ( ) ; }

Creates a while statement

@param sameDiffConditional
@param loopBody
@return


public Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> exec(String functionName) {
        if (debugMode) {
            return sameDiffFunctionInstances.get(functionName).enableDebugMode().exec();

        } else
            return sameDiffFunctionInstances.get(functionName).exec();
    }

public Pair < Map < SDVariable , DifferentialFunction > , List < DifferentialFunction > > exec ( String functionName ) { if ( debugMode ) { return sameDiffFunctionInstances . get ( functionName ) . enableDebugMode ( ) . exec ( ) ; } else return sameDiffFunctionInstances . get ( functionName ) . exec ( ) ; }

Exec a given function

@param functionName the opName of the function
to invoke
@return


public List<DifferentialFunction> exec(String functionName, List<DifferentialFunction> cachedOps) {
        return sameDiffFunctionInstances.get(functionName).exec(cachedOps);
    }

public List < DifferentialFunction > exec ( String functionName , List < DifferentialFunction > cachedOps ) { return sameDiffFunctionInstances . get ( functionName ) . exec ( cachedOps ) ; }

Exec the given function
given the ops

@param functionName the opName of the function to
exec
@param cachedOps    the cached operations
@return


public INDArray execBackwardAndEndResult() {
        List<DifferentialFunction> backwards = execBackwards().getRight();
        DifferentialFunction df = backwards.get(backwards.size() - 1);
        if (df instanceof Op) {
            return ((Op) df).z();
        } else if (df instanceof DynamicCustomOp) {
            return ((DynamicCustomOp) df).getOutputArgument(0);
        } else {
            return null;
        }
    }

public INDArray execBackwardAndEndResult ( ) { List < DifferentialFunction > backwards = execBackwards ( ) . getRight ( ) ; DifferentialFunction df = backwards . get ( backwards . size ( ) - 1 ) ; if ( df instanceof Op ) { return ( ( Op ) df ) . z ( ) ; } else if ( df instanceof DynamicCustomOp ) { return ( ( DynamicCustomOp ) df ) . getOutputArgument ( 0 ) ; } else { return null ; } }

Exec a backwards operation
and return the end result

@return


public void addAsPlaceHolder(String varName) {
        placeHolderVarNames.add(varName);
        if (getVariable(varName) != null && getVariable(varName).getShape() != null) {
            placeHolderOriginalShapes.put(varName, getVariable(varName).getShape());
        }
    }

public void addAsPlaceHolder ( String varName ) { placeHolderVarNames . add ( varName ) ; if ( getVariable ( varName ) != null && getVariable ( varName ) . getShape ( ) != null ) { placeHolderOriginalShapes . put ( varName , getVariable ( varName ) . getShape ( ) ) ; } }

Add  this vertex id as a place holder

@param varName the vertex id to add


@Override
    public Pointer allocate(long bytes, MemoryKind kind, boolean initialize) {
        AtomicAllocator allocator = AtomicAllocator.getInstance();

        //log.info("Allocating {} bytes in {} memory...", bytes, kind);

        if (kind == MemoryKind.HOST) {
            Pointer ptr = NativeOpsHolder.getInstance().getDeviceNativeOps().mallocHost(bytes, 0);

            if (ptr == null)
                throw new RuntimeException("Failed to allocate " + bytes + " bytes from HOST memory");

            if (initialize)
                Pointer.memset(ptr, 0, bytes);

            return ptr;//allocator.getMemoryHandler().alloc(AllocationStatus.HOST, null, null, initialize).getHostPointer();
        } else if (kind == MemoryKind.DEVICE) {
            Pointer ptr = NativeOpsHolder.getInstance().getDeviceNativeOps().mallocDevice(bytes, null, 0);

            //log.info("Allocating {} bytes for device_{}", bytes, Nd4j.getAffinityManager().getDeviceForCurrentThread());

            if (ptr == null)
                throw new RuntimeException("Failed to allocate " + bytes + " bytes from DEVICE [" + Nd4j.getAffinityManager().getDeviceForCurrentThread() + "] memory");

            if (initialize) {
                CudaContext context = (CudaContext) AtomicAllocator.getInstance().getDeviceContext().getContext();

                int i = NativeOpsHolder.getInstance().getDeviceNativeOps().memsetAsync(ptr, 0, bytes, 0, context.getSpecialStream());
                if (i == 0)
                    throw new ND4JIllegalStateException("memset failed on device_" + Nd4j.getAffinityManager().getDeviceForCurrentThread());

                context.getSpecialStream().synchronize();
            }

            return ptr; //allocator.getMemoryHandler().alloc(AllocationStatus.HOST, null, null, initialize).getDevicePointer();
        } else
            throw new RuntimeException("Unknown MemoryKind requested: " + kind);
    }

This method returns Pointer to allocated memory chunk

PLEASE NOTE: Cache options depend on specific implementations

@param bytes
@param kind
@param initialize


public static int lengthForDtype(DataBuffer.Type type) {
        switch (type) {
            case DOUBLE:
                return 8;
            case FLOAT:
                return 4;
            case INT:
                return 4;
            case HALF:
                return 2;
            case LONG:
                return 8;
            case COMPRESSED:
            default:
                throw new IllegalArgumentException("Illegal opType for length");

        }

    }

public
static
int
lengthForDtype
(
DataBuffer
.
Type
type
)
{
switch
(
type
)
{
case
DOUBLE
:
return
8
;
case
FLOAT
:
return
4
;
case
INT
:
return
4
;
case
HALF
:
return
2
;
case
LONG
:
return
8
;
case
COMPRESSED
:
default
:
throw
new
IllegalArgumentException
(
"Illegal opType for length"
)
;
}
}

Returns the length for the given data opType
@param type
@return


public static String getDTypeForName(DataBuffer.Type allocationMode) {
        switch (allocationMode) {
            case DOUBLE:
                return "double";
            case FLOAT:
                return "float";
            case INT:
                return "int";
            case HALF:
                return "half";
            default:
                return "float";
        }
    }

public static String getDTypeForName ( DataBuffer . Type allocationMode ) { switch ( allocationMode ) { case DOUBLE : return "double" ; case FLOAT : return "float" ; case INT : return "int" ; case HALF : return "half" ; default : return "float" ; } }

Gets the name of the alocation mode
@param allocationMode
@return


public static DataBuffer.Type getDtypeFromContext() {
        try {
            lock.readLock().lock();

            if (dtype == null) {
                lock.readLock().unlock();
                lock.writeLock().lock();

                if (dtype == null)
                    dtype = getDtypeFromContext(Nd4jContext.getInstance().getConf().getProperty("dtype"));

                lock.writeLock().unlock();
                lock.readLock().lock();
            }

            return dtype;
        } finally {
            lock.readLock().unlock();
        }
    }

public static DataBuffer . Type getDtypeFromContext ( ) { try { lock . readLock ( ) . lock ( ) ; if ( dtype == null ) { lock . readLock ( ) . unlock ( ) ; lock . writeLock ( ) . lock ( ) ; if ( dtype == null ) dtype = getDtypeFromContext ( Nd4jContext . getInstance ( ) . getConf ( ) . getProperty ( "dtype" ) ) ; lock . writeLock ( ) . unlock ( ) ; lock . readLock ( ) . lock ( ) ; } return dtype ; } finally { lock . readLock ( ) . unlock ( ) ; } }

get the allocation mode from the context
@return


@Override
    public int getOpNumByName(String opName) {
        try {
            DifferentialFunction op =  DifferentialFunctionClassHolder.getInstance().getInstance(opName);
            return  op.opNum();
        } catch (Exception e) {
            throw new RuntimeException("OpName failed: [" + opName + "]",e);
        }
    }

@
Override
public
int
getOpNumByName
(
String
opName
)
{
try
{
DifferentialFunction
op
=
DifferentialFunctionClassHolder
.
getInstance
(
)
.
getInstance
(
opName
)
;
return
op
.
opNum
(
)
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"OpName failed: ["
+
opName
+
"]"
,
e
)
;
}
}

This method returns op id number for given opName

@param opName
@return


@Override
    public void destroyAllWorkspacesForCurrentThread() {
        ensureThreadExistense();

        List<MemoryWorkspace> workspaces = new ArrayList<>();
        workspaces.addAll(backingMap.get().values());

        for (MemoryWorkspace workspace : workspaces) {
            destroyWorkspace(workspace);
        }

        System.gc();
    }

@ Override public void destroyAllWorkspacesForCurrentThread ( ) { ensureThreadExistense ( ) ; List < MemoryWorkspace > workspaces = new ArrayList <> ( ) ; workspaces . addAll ( backingMap . get ( ) . values ( ) ) ; for ( MemoryWorkspace workspace : workspaces ) { destroyWorkspace ( workspace ) ; } System . gc ( ) ; }

This method destroys all workspaces allocated in current thread


public synchronized void printAllocationStatisticsForCurrentThread() {
        ensureThreadExistense();
        Map<String, MemoryWorkspace> map = backingMap.get();
        log.info("Workspace statistics: ---------------------------------");
        log.info("Number of workspaces in current thread: {}", map.size());
        log.info("Workspace name: Allocated / external (spilled) / external (pinned)");
        for (String key : map.keySet()) {
            long current = ((Nd4jWorkspace) map.get(key)).getCurrentSize();
            long spilled = ((Nd4jWorkspace) map.get(key)).getSpilledSize();
            long pinned = ((Nd4jWorkspace) map.get(key)).getPinnedSize();
            log.info(String.format("%-26s %8s / %8s / %8s (%11d / %11d / %11d)", (key + ":"),
                    StringUtils.TraditionalBinaryPrefix.long2String(current, "", 2),
                    StringUtils.TraditionalBinaryPrefix.long2String(spilled, "", 2),
                    StringUtils.TraditionalBinaryPrefix.long2String(pinned, "", 2),
                    current, spilled, pinned));
        }
    }

This method prints out basic statistics for workspaces allocated in current thread


@Override
    public void trmv(char order, char Uplo, char TransA, char Diag, INDArray A, INDArray X) {
        if (Nd4j.getExecutioner().getProfilingMode() == OpExecutioner.ProfilingMode.ALL)
            OpProfiler.getInstance().processBlasCall(false, A, X);

        // FIXME: int cast

        if (A.data().dataType() == DataBuffer.Type.DOUBLE) {
            DefaultOpExecutioner.validateDataType(DataBuffer.Type.DOUBLE, A, X);
            dtrmv(order, Uplo, TransA, Diag, (int) X.length(), A, (int) A.size(0), X, X.majorStride());
        } else {
            DefaultOpExecutioner.validateDataType(DataBuffer.Type.FLOAT, A, X);
            strmv(order, Uplo, TransA, Diag, (int) X.length(), A, (int) A.size(0), X, X.majorStride());
        }

        OpExecutionerUtil.checkForAny(X);
    }

@
Override
public
void
trmv
(
char
order
,
char
Uplo
,
char
TransA
,
char
Diag
,
INDArray
A
,
INDArray
X
)
{
if
(
Nd4j
.
getExecutioner
(
)
.
getProfilingMode
(
)
==
OpExecutioner
.
ProfilingMode
.
ALL
)
OpProfiler
.
getInstance
(
)
.
processBlasCall
(
false
,
A
,
X
)
;
// FIXME: int cast
if
(
A
.
data
(
)
.
dataType
(
)
==
DataBuffer
.
Type
.
DOUBLE
)
{
DefaultOpExecutioner
.
validateDataType
(
DataBuffer
.
Type
.
DOUBLE
,
A
,
X
)
;
dtrmv
(
order
,
Uplo
,
TransA
,
Diag
,
(
int
)
X
.
length
(
)
,
A
,
(
int
)
A
.
size
(
0
)
,
X
,
X
.
majorStride
(
)
)
;
}
else
{
DefaultOpExecutioner
.
validateDataType
(
DataBuffer
.
Type
.
FLOAT
,
A
,
X
)
;
strmv
(
order
,
Uplo
,
TransA
,
Diag
,
(
int
)
X
.
length
(
)
,
A
,
(
int
)
A
.
size
(
0
)
,
X
,
X
.
majorStride
(
)
)
;
}
OpExecutionerUtil
.
checkForAny
(
X
)
;
}

trmv computes a matrix-vector product using a triangular matrix.

@param order
@param Uplo
@param TransA
@param Diag
@param A
@param X

trmv computes a matrix - vector product using a triangular matrix .


public INDArray receive() {
        if (consumerTemplate == null)
            consumerTemplate = camelContext.createConsumerTemplate();
        return consumerTemplate.receiveBody("direct:receive", INDArray.class);
    }

public INDArray receive ( ) { if ( consumerTemplate == null ) consumerTemplate = camelContext . createConsumerTemplate ( ) ; return consumerTemplate . receiveBody ( "direct:receive" , INDArray . class ) ; }


@Override
    public INDArray exec(Variance accumulation, boolean biasCorrected, int... dimension) {
        return processOp(accumulation).z();
    }

@ Override public INDArray exec ( Variance accumulation , boolean biasCorrected , int ... dimension ) { return processOp ( accumulation ) . z ( ) ; }

Execute an accumulation along one or more dimensions

@param accumulation  the accumulation
@param biasCorrected
@param dimension     the dimension  @return the accmulation op


@Override
    public INDArray thresholdDecode(INDArray encoded, INDArray target) {
        return backendExecutioner.thresholdDecode(encoded,target);
    }

@ Override public INDArray thresholdDecode ( INDArray encoded , INDArray target ) { return backendExecutioner . thresholdDecode ( encoded , target ) ; }

This method decodes thresholds array, and puts it into target array

@param encoded
@param target
@return target is returned

This method decodes thresholds array and puts it into target array


public String getNodeName(String name) {
        //tensorflow adds colons to the end of variables representing input index, this strips those off
        String ret = name;
        if(ret.startsWith("^"))
            ret = ret.substring(1);
        if(ret.endsWith("/read")) {
            ret = ret.replace("/read","");
        }
        return ret;
    }

Map a tensorflow node name
to the samediff equivalent
for import
@param name the name to change
@return the input tensorflow name


private void invoke(ScalarOp op, int[] dimension) {
        dimension = Shape.normalizeAxis(op.x().rank(), dimension);
        // do tad magic
        /**
         * Returns the {@link Shape#createShapeInformation(int[], int[], int, int, char)}
         * and the associated offsets for each {@link INDArray#tensorAlongDimension(int, int...)}
         * The first item is the shape information. The second one is the offsets.
         */
        Pair<DataBuffer, DataBuffer> tadBuffers = tadManager.getTADOnlyShapeInfo(op.x(), dimension);

        Pointer hostTadShapeInfo = tadBuffers.getFirst().addressPointer();
        Pointer hostTadOffsets = tadBuffers.getSecond().addressPointer();

        Pointer devTadShapeInfoZ = null;
        Pointer devTadOffsetsZ = null;
        /**
         * Returns the {@link Shape#createShapeInformation(int[], int[], int, int, char)}
         * and the associated offsets for each {@link INDArray#tensorAlongDimension(int, int...)}
         * The first item is the shape information. The second one is the offsets.
         *
         * Note that this is the *result* TAD information. An op is always input (x) and output (z)
         * for result.
         * This is for assigning the result to of the operation along
         * the proper dimension.
         */
        Pair<DataBuffer, DataBuffer> tadBuffersZ = tadManager.getTADOnlyShapeInfo(op.z(), dimension);

        devTadShapeInfoZ = tadBuffersZ.getFirst().addressPointer();
        devTadOffsetsZ = tadBuffersZ.getSecond().addressPointer();

        if (extraz.get() == null)
            extraz.set(new PointerPointer(32));

        PointerPointer dummy = extraz.get().put(hostTadShapeInfo, hostTadOffsets, devTadShapeInfoZ, devTadOffsetsZ);

        if (op.x().data().dataType() == DataBuffer.Type.FLOAT) {
            loop.execScalarFloat(dummy, op.opNum(), (FloatPointer) op.x().data().addressPointer(),
                    (LongPointer) op.x().shapeInfoDataBuffer().addressPointer(),
                    (FloatPointer) op.z().data().addressPointer(),
                    (LongPointer) op.z().shapeInfoDataBuffer().addressPointer(),
                    (FloatPointer) op.y().data().addressPointer(), (FloatPointer) getPointerForExtraArgs(op),
                    (IntPointer) Nd4j.getConstantHandler().getConstantBuffer(dimension).addressPointer(), dimension.length);
        } else if (op.x().data().dataType() == DataBuffer.Type.DOUBLE) {
            loop.execScalarDouble(dummy, op.opNum(), (DoublePointer) op.x().data().addressPointer(),
                    (LongPointer) op.x().shapeInfoDataBuffer().addressPointer(),
                    (DoublePointer) op.z().data().addressPointer(),
                    (LongPointer) op.z().shapeInfoDataBuffer().addressPointer(),
                    (DoublePointer) op.y().data().addressPointer(), (DoublePointer) getPointerForExtraArgs(op),
                    (IntPointer) Nd4j.getConstantHandler().getConstantBuffer(dimension).addressPointer(), dimension.length);
        }
    }

ScalarOp along dimension
@param op
@param dimension


public static void assertNoWorkspacesOpen(String msg) throws ND4JWorkspaceException {
        if (Nd4j.getWorkspaceManager().anyWorkspaceActiveForCurrentThread()) {
            List<MemoryWorkspace> l = Nd4j.getWorkspaceManager().getAllWorkspacesForCurrentThread();
            List<String> workspaces = new ArrayList<>(l.size());
            for (MemoryWorkspace ws : l) {
                if(ws.isScopeActive()) {
                    workspaces.add(ws.getId());
                }
            }
            throw new ND4JWorkspaceException(msg + " - Open/active workspaces: " + workspaces);
        }
    }

public
static
void
assertNoWorkspacesOpen
(
String
msg
)
throws
ND4JWorkspaceException
{
if
(
Nd4j
.
getWorkspaceManager
(
)
.
anyWorkspaceActiveForCurrentThread
(
)
)
{
List
<
MemoryWorkspace
>
l
=
Nd4j
.
getWorkspaceManager
(
)
.
getAllWorkspacesForCurrentThread
(
)
;
List
<
String
>
workspaces
=
new
ArrayList
<>
(
l
.
size
(
)
)
;
for
(
MemoryWorkspace
ws
:
l
)
{
if
(
ws
.
isScopeActive
(
)
)
{
workspaces
.
add
(
ws
.
getId
(
)
)
;
}
}
throw
new
ND4JWorkspaceException
(
msg
+
" - Open/active workspaces: "
+
workspaces
)
;
}
}

Assert that no workspaces are currently open

@param msg Message to include in the exception, if required


private INDArray negativeLogLikelihood(INDArray labels, INDArray alpha, INDArray mu, INDArray sigma) {
        INDArray labelsMinusMu = labelsMinusMu(labels, mu);
        INDArray diffsquared = labelsMinusMu.mul(labelsMinusMu).sum(2);
        INDArray phitimesalphasum = phi(diffsquared, sigma).muli(alpha).sum(1);

        // result = See Bishop(28,29)
        INDArray result = Transforms.log(phitimesalphasum).negi();
        return result;
    }

private
INDArray
negativeLogLikelihood
(
INDArray
labels
,
INDArray
alpha
,
INDArray
mu
,
INDArray
sigma
)
{
INDArray
labelsMinusMu
=
labelsMinusMu
(
labels
,
mu
)
;
INDArray
diffsquared
=
labelsMinusMu
.
mul
(
labelsMinusMu
)
.
sum
(
2
)
;
INDArray
phitimesalphasum
=
phi
(
diffsquared
,
sigma
)
.
muli
(
alpha
)
.
sum
(
1
)
;
// result = See Bishop(28,29)
INDArray
result
=
Transforms
.
log
(
phitimesalphasum
)
.
negi
(
)
;
return
result
;
}

This method returns an array consisting of each of the training samples,
for each label in each sample, the negative log likelihood of that
value falling within the given gaussian mixtures.
@param alpha
@param mu
@param sigma
@param labels
@return

This method returns an array consisting of each of the training samples for each label in each sample the negative log likelihood of that value falling within the given gaussian mixtures .


public void requestTick(long time, TimeUnit timeUnit) {
        long timeframeMs = TimeUnit.MILLISECONDS.convert(time, timeUnit);
        long currentTime = System.currentTimeMillis();
        boolean isWaiting = false;

        // if we have Toe request queued - we' have to wait till it finishes.
        try {
            while (isToeScheduled.get() || isToeWaiting.get() || getCurrentState() == AccessState.TOE) {
                if (!isWaiting) {
                    isWaiting = true;
                    waitingTicks.incrementAndGet();
                }
                Thread.sleep(50);
            }

            currentState.set(AccessState.TICK.ordinal());
            waitingTicks.decrementAndGet();
            tickRequests.incrementAndGet();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

This method requests to change state to Tick.

PLEASE NOTE: this method is blocking, if memory is in Toe state.
PLEASE NOTE: if Tick can't be acquired within specified timeframe, exception will be thrown

@param time
@param timeUnit

This method requests to change state to Tick .


public boolean tryRequestToe() {
        scheduleToe();
        if (isToeWaiting.get() || getCurrentState() == AccessState.TOE) {
            //System.out.println("discarding TOE");
            discardScheduledToe();
            return false;
        } else {
            //System.out.println("requesting TOE");
            discardScheduledToe();
            requestToe();
            return true;
        }
    }

public
boolean
tryRequestToe
(
)
{
scheduleToe
(
)
;
if
(
isToeWaiting
.
get
(
)
||
getCurrentState
(
)
==
AccessState
.
TOE
)
{
//System.out.println("discarding TOE");
discardScheduledToe
(
)
;
return
false
;
}
else
{
//System.out.println("requesting TOE");
discardScheduledToe
(
)
;
requestToe
(
)
;
return
true
;
}
}

This method requests to change state to Toe

PLEASE NOTE: this method is non-blocking, if Toe request is impossible atm, it will return false.

@return TRUE, if Toe state entered, FALSE otherwise


public void releaseToe() {
        if (getCurrentState() == AccessState.TOE) {
            if (1 > 0) {
                //if (toeThread.get() == Thread.currentThread().getId()) {
                if (toeRequests.decrementAndGet() == 0) {
                    tickRequests.set(0);
                    tackRequests.set(0);

                    currentState.set(AccessState.TACK.ordinal());
                }
            } else
                throw new IllegalStateException("releaseToe() is called from different thread.");
        } else
            throw new IllegalStateException("Object is NOT in Toe state!");
    }

This method requests release Toe status back to Tack.

PLEASE NOTE: only the thread originally entered Toe state is able to release it.

This method requests release Toe status back to Tack .


public AccessState getCurrentState() {
        if (AccessState.values()[currentState.get()] == AccessState.TOE) {
            return AccessState.TOE;
        } else {
            if (tickRequests.get() <= tackRequests.get()) {

                // TODO: looks like this piece of code should be locked :/
                tickRequests.set(0);
                tackRequests.set(0);

                return AccessState.TACK;
            } else
                return AccessState.TICK;
        }
    }

This method returns the current memory state

@return


public static Environment buildEnvironment() {
        Environment environment = new Environment();

        environment.setJavaVersion(System.getProperty("java.specification.version"));
        environment.setNumCores(Runtime.getRuntime().availableProcessors());
        environment.setAvailableMemory(Runtime.getRuntime().maxMemory());
        environment.setOsArch(System.getProperty("os.arch"));
        environment.setOsName(System.getProperty("os.opName"));
        environment.setBackendUsed(Nd4j.getExecutioner().getClass().getSimpleName());

        return environment;
    }

public static Environment buildEnvironment ( ) { Environment environment = new Environment ( ) ; environment . setJavaVersion ( System . getProperty ( "java.specification.version" ) ) ; environment . setNumCores ( Runtime . getRuntime ( ) . availableProcessors ( ) ) ; environment . setAvailableMemory ( Runtime . getRuntime ( ) . maxMemory ( ) ) ; environment . setOsArch ( System . getProperty ( "os.arch" ) ) ; environment . setOsName ( System . getProperty ( "os.opName" ) ) ; environment . setBackendUsed ( Nd4j . getExecutioner ( ) . getClass ( ) . getSimpleName ( ) ) ; return environment ; }


@Override
    public void processMessage() {
        if (clipboard.isTracking(this.originatorId, this.getTaskId())) {
            clipboard.pin(this);

            if (clipboard.isReady(this.originatorId, taskId)) {
                VoidAggregation aggregation = clipboard.unpin(this.originatorId, taskId);

                // FIXME: probably there's better solution, then "screw-and-forget" one
                if (aggregation == null)
                    return;

                VectorCompleteMessage msg = new VectorCompleteMessage(taskId, aggregation.getAccumulatedResult());
                msg.setOriginatorId(aggregation.getOriginatorId());
                transport.sendMessage(msg);
            }
        }
    }

Vector aggregations are saved only by Shards started aggregation process. All other Shards are ignoring this meesage

Vector aggregations are saved only by Shards started aggregation process . All other Shards are ignoring this meesage


protected void initializeCurrFromList(List<DataSet> examples) {

        if (examples.isEmpty())
            log.warn("Warning: empty dataset from the fetcher");

        INDArray inputs = createInputMatrix(examples.size());
        INDArray labels = createOutputMatrix(examples.size());
        for (int i = 0; i < examples.size(); i++) {
            inputs.putRow(i, examples.get(i).getFeatureMatrix());
            labels.putRow(i, examples.get(i).getLabels());
        }
        curr = new DataSet(inputs, labels);

    }

Initializes this data transform fetcher from the passed in datasets

@param examples the examples to use


protected void initHostCollectors() {
        for (int i = 0; i < configuration.getNumberOfGcThreads(); i++) {
            ReferenceQueue<BaseDataBuffer> queue = new ReferenceQueue<>();

            UnifiedGarbageCollectorThread uThread = new UnifiedGarbageCollectorThread(i, queue);

            // all GC threads should be attached to default device
            Nd4j.getAffinityManager().attachThreadToDevice(uThread, getDeviceId());

            queueMap.put(i, queue);

            uThread.start();

            collectorsUnified.put(i, uThread);
            /*
            ZeroGarbageCollectorThread zThread = new ZeroGarbageCollectorThread((long) i, shouldStop);
            zThread.start();

            collectorsZero.put((long) i, zThread);
            */
        }
    }

This method executes preconfigured number of host memory garbage collectors


@Override
    public Pointer getPointer(DataBuffer buffer, CudaContext context) {
        return memoryHandler.getDevicePointer(buffer, context);
    }

@ Override public Pointer getPointer ( DataBuffer buffer , CudaContext context ) { return memoryHandler . getDevicePointer ( buffer , context ) ; }

This method returns actual device pointer valid for current object

@param buffer


@Override
    public void synchronizeHostData(DataBuffer buffer) {
        // we don't want non-committed ops left behind
        //Nd4j.getExecutioner().push();

        // we don't synchronize constant buffers, since we assume they are always valid on host side
        if (buffer.isConstant()) {
            return;
        }

        // we actually need synchronization only in device-dependant environment. no-op otherwise
        if (memoryHandler.isDeviceDependant()) {
            AllocationPoint point = getAllocationPoint(buffer.getTrackingPoint());
            if (point == null)
                throw new RuntimeException("AllocationPoint is NULL");
            memoryHandler.synchronizeThreadDevice(Thread.currentThread().getId(), memoryHandler.getDeviceId(), point);
        }
    }

This method should be called to make sure that data on host side is actualized

@param buffer


@Override
    public void applyUpdater(INDArray gradient, int iteration, int epoch) {
        if (historicalGradient == null)
            throw new IllegalStateException("Updater has not been initialized with view state");

        double learningRate = config.getLearningRate(iteration, epoch);
        double epsilon = config.getEpsilon();

        historicalGradient.addi(gradient.mul(gradient));

        INDArray sqrtHistory = sqrt(historicalGradient.dup(gradientReshapeOrder), false).addi(epsilon);
        // lr * gradient / (sqrt(sumSquaredGradients) + epsilon)
        gradient.muli(sqrtHistory.rdivi(learningRate));
    }

Gets feature specific learning rates
Adagrad keeps a history of gradients being passed in.
Note that each gradient passed in becomes adapted over time, hence the opName adagrad

@param gradient  the gradient to get learning rates for
@param iteration

Gets feature specific learning rates Adagrad keeps a history of gradients being passed in . Note that each gradient passed in becomes adapted over time hence the opName adagrad


@Override
    public void synchronizeToHost(AllocationPoint point) {
        if (!point.isConstant() && point.isEnqueued()) {
            waitTillFinished(point);
        }

        super.synchronizeToHost(point);
    }

@ Override public void synchronizeToHost ( AllocationPoint point ) { if ( ! point . isConstant ( ) && point . isEnqueued ( ) ) { waitTillFinished ( point ) ; } super . synchronizeToHost ( point ) ; }

This method makes sure HOST memory contains latest data from GPU

Additionally, this method checks, that there's no ops pending execution for this array

@param point


public static INDArrayIndex[] create(INDArray index) {

        if (index.isMatrix()) {

            if (index.rows() > Integer.MAX_VALUE)
                throw new ND4JArraySizeException();

            NDArrayIndex[] ret = new NDArrayIndex[(int) index.rows()];
            for (int i = 0; i < index.rows(); i++) {
                INDArray row = index.getRow(i);
                val nums = new long[(int) index.getRow(i).columns()];
                for (int j = 0; j < row.columns(); j++) {
                    nums[j] = (int) row.getFloat(j);
                }

                NDArrayIndex idx = new NDArrayIndex(nums);
                ret[i] = idx;

            }

            return ret;

        } else if (index.isVector()) {
            long[] indices = NDArrayUtil.toLongs(index);
            return new NDArrayIndex[] {new NDArrayIndex(indices)};
        }

        throw new IllegalArgumentException("Passed in ndarray must be a matrix or a vector");

    }

Create from a matrix. The rows are the indices
The columns are the individual element in each ndarrayindex

@param index the matrix to getFloat indices from
@return the indices to getFloat

Create from a matrix . The rows are the indices The columns are the individual element in each ndarrayindex


public Map<String,Object> propertiesForFunction() {
        val fields = DifferentialFunctionClassHolder.getInstance().getFieldsForFunction(this);
        Map<String,Object> ret = new LinkedHashMap<>();

        for(val entry : fields.entrySet()) {
            try {
                ret.put(entry.getKey(),fields.get(entry.getKey()).get(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        return ret;
    }

public Map < String , Object > propertiesForFunction ( ) { val fields = DifferentialFunctionClassHolder . getInstance ( ) . getFieldsForFunction ( this ) ; Map < String , Object > ret = new LinkedHashMap <> ( ) ; for ( val entry : fields . entrySet ( ) ) { try { ret . put ( entry . getKey ( ) , fields . get ( entry . getKey ( ) ) . get ( this ) ) ; } catch ( IllegalAccessException e ) { e . printStackTrace ( ) ; } } return ret ; }

Returns the properties for a given function
@return


public boolean hasPlaceHolderInputs() {
        val args = args();
        for(val arg : args)
            if(sameDiff.hasPlaceHolderVariables(arg().getVarName()))
                return true;
        return false;
    }

public boolean hasPlaceHolderInputs ( ) { val args = args ( ) ; for ( val arg : args ) if ( sameDiff . hasPlaceHolderVariables ( arg ( ) . getVarName ( ) ) ) return true ; return false ; }

Returns true if this
function has place holder inputs
@return


public List<SDVariable> diff(List<SDVariable> i_v1) {
        List<SDVariable> vals = doDiff(i_v1);
        if(vals == null){
            throw new IllegalStateException("Error executing diff operation: doDiff returned null for op: " + this.opName());
        }

        val outputVars = args();
        for(int i = 0; i < vals.size(); i++) {
            SDVariable var = outputVars[i];
            SDVariable grad = var.getGradient();
            if(grad != null) {
                SDVariable gradVar =  f().add(grad, vals.get(i));
                try {
                    vals.set(i, gradVar);
                } catch (UnsupportedOperationException e){
                    throw new UnsupportedOperationException("Use a mutable list when returning values from "+this.getClass().getSimpleName()+".doDiff (e.g. Arrays.asList instead of Collections.singletonList)", e);
                }
                sameDiff.setGradientForVariableName(var.getVarName(), gradVar);
            } else {
                SDVariable gradVar = vals.get(i);
                sameDiff.updateVariableNameAndReference(gradVar,var.getVarName() + "-grad");
                sameDiff.setGradientForVariableName(var.getVarName(), gradVar);
                sameDiff.setForwardVariableForVarName(gradVar.getVarName(),var);

            }
        }

        return vals;
    }

Perform automatic differentiation
wrt the input variables
@param i_v1 the input variables
@return the differentiated output
wrt each input variable


public String format(INDArray arr, boolean summarize) {
        this.scientificFormat = "0.";
        int addPrecision = this.precision;
        while (addPrecision > 0) {
            this.scientificFormat += "#";
            addPrecision -= 1;
        }
        this.scientificFormat = this.scientificFormat + "E0";
        if (this.scientificFormat.length() + 2  > this.padding) this.padding = this.scientificFormat.length() + 2;
        this.maxToPrintWithoutSwitching = Math.pow(10,this.precision);
        this.minToPrintWithoutSwitching = 1.0/(this.maxToPrintWithoutSwitching);
        if (summarize && arr.length() > 1000) return format(arr, 0, true);
        return format(arr, 0, false);
    }

public String format ( INDArray arr , boolean summarize ) { this . scientificFormat = "0." ; int addPrecision = this . precision ; while ( addPrecision > 0 ) { this . scientificFormat += "#" ; addPrecision -= 1 ; } this . scientificFormat = this . scientificFormat + "E0" ; if ( this . scientificFormat . length ( ) + 2 > this . padding ) this . padding = this . scientificFormat . length ( ) + 2 ; this . maxToPrintWithoutSwitching = Math . pow ( 10 , this . precision ) ; this . minToPrintWithoutSwitching = 1.0 / ( this . maxToPrintWithoutSwitching ) ; if ( summarize && arr . length ( ) > 1000 ) return format ( arr , 0 , true ) ; return format ( arr , 0 , false ) ; }

Format the given ndarray as a string

@param arr       the array to format
@param summarize If true and the number of elements in the array is greater than > 1000 only the first three and last elements in any dimension will print
@return the formatted array


@Override
    public SameDiff importGraph(GRAPH_TYPE tfGraph) {
        SameDiff diff = SameDiff.create();
        ImportState<GRAPH_TYPE,TENSOR_TYPE> importState = new ImportState<>();
        importState.setSameDiff(diff);
        importState.setGraph(tfGraph);

        val variablesForGraph = variablesForGraph(tfGraph);
        importState.setVariables(variablesForGraph);

        //map the names of the nodes while accumulating the vertex ids
        //for each variable
        for(Map.Entry<String,TENSOR_TYPE> entry : variablesForGraph.entrySet()) {
            if(dataTypeForTensor(entry.getValue()) == DataBuffer.Type.UNKNOWN) {
                val var = importState.getSameDiff().var(entry.getKey(),null,new ZeroInitScheme('c'));
                //mark as place holder for validating resolution later.
                if(isPlaceHolder(entry.getValue())) {
                    importState.getSameDiff().addAsPlaceHolder(var.getVarName());
                    if(var.getShape() != null)
                        importState.getSameDiff().setOriginalPlaceHolderShape(var.getVarName(),var.getShape());
                }

                continue;
            }

            val arr = getNDArrayFromTensor(entry.getKey(), entry.getValue(), tfGraph);
            if(arr != null) {
                val var = importState.getSameDiff().var(entry.getKey(),arr);
                //ensure the array is made available for later processing
                diff.associateArrayWithVariable(arr,var);
            }
            else if(getShapeFromTensor(entry.getValue()) == null) {
                val var = importState.getSameDiff().var(entry.getKey(),null,new ZeroInitScheme('c'));
                //mark as place holder for validating resolution later.

                //note that this vertex id can still be a place holder
                //with a -1 shape. Just because a shape is "known" doesn't mean
                //that it isn't  a place holder.
                if(isPlaceHolder(entry.getValue())) {
                    val originalShape = getShapeFromTensor(entry.getValue());
                    importState.getSameDiff().addAsPlaceHolder(var.getVarName());
                    if(var.getShape() != null)
                        importState.getSameDiff().setOriginalPlaceHolderShape(var.getVarName(),originalShape);

                }

            }
            else {
                val originalShape = getShapeFromTensor(entry.getValue());
                val var = importState.getSameDiff().var(entry.getKey(),originalShape);
                //mark as place holder for validating resolution later.

                //note that this vertex id can still be a place holder
                //with a -1 shape. Just because a shape is "known" doesn't mean
                //that it isn't  a place holder.
                if(isPlaceHolder(entry.getValue())) {
                    importState.getSameDiff().addAsPlaceHolder(var.getVarName());
                    importState.getSameDiff().setOriginalPlaceHolderShape(var.getVarName(),originalShape);
                }

            }

        }

        //setup vertex ids for  names

        //handle mapping vertex ids properly

        val tfNodesList = getNodeList(tfGraph);
        for (NODE_TYPE tfNode : tfNodesList) {
            if(!opsToIgnore().contains(getOpType(tfNode)) || isOpIgnoreException(tfNode))
                mapNodeType(tfNode,importState);
        }

        return diff;
    }

This method converts given TF
@param tfGraph
@return


@Override
    public Blob convert(IComplexNDArray toConvert) throws IOException, SQLException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);

        Nd4j.writeComplex(toConvert, dos);

        byte[] bytes = bos.toByteArray();
        Connection c = dataSource.getConnection();
        Blob b = c.createBlob();
        b.setBytes(1, bytes);
        return b;
    }

@ Override public Blob convert ( IComplexNDArray toConvert ) throws IOException , SQLException { ByteArrayOutputStream bos = new ByteArrayOutputStream ( ) ; DataOutputStream dos = new DataOutputStream ( bos ) ; Nd4j . writeComplex ( toConvert , dos ) ; byte [ ] bytes = bos . toByteArray ( ) ; Connection c = dataSource . getConnection ( ) ; Blob b = c . createBlob ( ) ; b . setBytes ( 1 , bytes ) ; return b ; }

Convert an ndarray to a blob

@param toConvert the complex ndarray to convert
@return the converted complex ndarray


@Override
    public IComplexNDArray loadComplex(Blob blob) throws SQLException, IOException {
        DataInputStream dis = new DataInputStream(blob.getBinaryStream());
        return Nd4j.readComplex(dis);
    }

@ Override public IComplexNDArray loadComplex ( Blob blob ) throws SQLException , IOException { DataInputStream dis = new DataInputStream ( blob . getBinaryStream ( ) ) ; return Nd4j . readComplex ( dis ) ; }

Load a complex ndarray from a blob

@param blob the blob to load from
@return the complex ndarray


@Override
    public void save(IComplexNDArray save, String id) throws IOException, SQLException {
        doSave(save, id);
    }

@ Override public void save ( IComplexNDArray save , String id ) throws IOException , SQLException { doSave ( save , id ) ; }

Save the ndarray

@param save the ndarray to save


protected void copyRealTo(INDArray arr) {
        INDArray linear = arr.linearView();
        IComplexNDArray thisLinear = linearView();
        if (arr.isScalar())
            arr.putScalar(0, getReal(0));
        else
            for (int i = 0; i < linear.length(); i++) {
                arr.putScalar(i, thisLinear.getReal(i));
            }

    }

protected void copyRealTo ( INDArray arr ) { INDArray linear = arr . linearView ( ) ; IComplexNDArray thisLinear = linearView ( ) ; if ( arr . isScalar ( ) ) arr . putScalar ( 0 , getReal ( 0 ) ) ; else for ( int i = 0 ; i < linear . length ( ) ; i ++ ) { arr . putScalar ( i , thisLinear . getReal ( i ) ) ; } }

Copy real numbers to arr
@param arr the arr to copy to


protected void copyImagTo(INDArray arr) {
        INDArray linear = arr.linearView();
        IComplexNDArray thisLinear = linearView();
        if (arr.isScalar())
            arr.putScalar(0, getReal(0));
        else
            for (int i = 0; i < linear.length(); i++) {
                arr.putScalar(i, thisLinear.getImag(i));
            }

    }

protected void copyImagTo ( INDArray arr ) { INDArray linear = arr . linearView ( ) ; IComplexNDArray thisLinear = linearView ( ) ; if ( arr . isScalar ( ) ) arr . putScalar ( 0 , getReal ( 0 ) ) ; else for ( int i = 0 ; i < linear . length ( ) ; i ++ ) { arr . putScalar ( i , thisLinear . getImag ( i ) ) ; } }

Copy imaginary numbers to the given
ndarray
@param arr the array to copy imaginary numbers to


@Override
    public IComplexNDArray epsi(Number other) {
        IComplexNDArray linear = linearView();
        double otherVal = other.doubleValue();
        for (int i = 0; i < linearView().length(); i++) {
            IComplexNumber n = linear.getComplex(i);
            double real = n.realComponent().doubleValue();
            double diff = Math.abs(real - otherVal);
            if (diff <= Nd4j.EPS_THRESHOLD)
                linear.putScalar(i, Nd4j.createDouble(1, 0));
            else
                linear.putScalar(i, Nd4j.createDouble(0, 0));
        }

        return this;
    }

@ Override public IComplexNDArray epsi ( Number other ) { IComplexNDArray linear = linearView ( ) ; double otherVal = other . doubleValue ( ) ; for ( int i = 0 ; i < linearView ( ) . length ( ) ; i ++ ) { IComplexNumber n = linear . getComplex ( i ) ; double real = n . realComponent ( ) . doubleValue ( ) ; double diff = Math . abs ( real - otherVal ) ; if ( diff <= Nd4j . EPS_THRESHOLD ) linear . putScalar ( i , Nd4j . createDouble ( 1 , 0 ) ) ; else linear . putScalar ( i , Nd4j . createDouble ( 0 , 0 ) ) ; } return this ; }

Returns an ndarray with 1 if the element is epsilon equals

@param other the number to compare
@return a copied ndarray with the given
binary conditions


@Override
    public IComplexNDArray assign(IComplexNDArray arr) {
        if (!arr.isScalar())
            LinAlgExceptions.assertSameLength(this, arr);
        IComplexNDArray linear = linearView();
        IComplexNDArray otherLinear = arr.linearView();
        for (int i = 0; i < linear.length(); i++) {
            linear.putScalar(i, otherLinear.getComplex(i));
        }

        return this;
    }

@ Override public IComplexNDArray assign ( IComplexNDArray arr ) { if ( ! arr . isScalar ( ) ) LinAlgExceptions . assertSameLength ( this , arr ) ; IComplexNDArray linear = linearView ( ) ; IComplexNDArray otherLinear = arr . linearView ( ) ; for ( int i = 0 ; i < linear . length ( ) ; i ++ ) { linear . putScalar ( i , otherLinear . getComplex ( i ) ) ; } return this ; }

Assign all of the elements in the given
ndarray to this ndarray

@param arr the elements to assign
@return this


@Override
    public IComplexNDArray getRows(int[] rindices) {
        INDArray rows = Nd4j.create(rindices.length, columns());
        for (int i = 0; i < rindices.length; i++) {
            rows.putRow(i, getRow(rindices[i]));
        }
        return (IComplexNDArray) rows;
    }

@ Override public IComplexNDArray getRows ( int [ ] rindices ) { INDArray rows = Nd4j . create ( rindices . length , columns ( ) ) ; for ( int i = 0 ; i < rindices . length ; i ++ ) { rows . putRow ( i , getRow ( rindices [ i ] ) ) ; } return ( IComplexNDArray ) rows ; }

Get whole rows from the passed indices.

@param rindices

Get whole rows from the passed indices .


@Override
    public IComplexNDArray putRow(long row, INDArray toPut) {
        return (IComplexNDArray) super.putRow(row, toPut);
    }

@ Override public IComplexNDArray putRow ( long row , INDArray toPut ) { return ( IComplexNDArray ) super . putRow ( row , toPut ) ; }

Insert a row in to this array
Will throw an exception if this
ndarray is not a matrix

@param row   the row insert into
@param toPut the row to insert
@return this


@Override
    public IComplexNDArray putColumn(int column, INDArray toPut) {
        assert toPut.isVector() && toPut.length() == rows() : "Illegal length for row " + toPut.length()
                        + " should have been " + columns();
        IComplexNDArray r = getColumn(column);
        if (toPut instanceof IComplexNDArray) {
            IComplexNDArray putComplex = (IComplexNDArray) toPut;
            for (int i = 0; i < r.length(); i++) {
                IComplexNumber n = putComplex.getComplex(i);
                r.putScalar(i, n);
            }
        } else {
            for (int i = 0; i < r.length(); i++)
                r.putScalar(i, Nd4j.createDouble(toPut.getDouble(i), 0));

        }

        return this;
    }

@
Override
public
IComplexNDArray
putColumn
(
int
column
,
INDArray
toPut
)
{
assert
toPut
.
isVector
(
)
&&
toPut
.
length
(
)
==
rows
(
)
:
"Illegal length for row "
+
toPut
.
length
(
)
+
" should have been "
+
columns
(
)
;
IComplexNDArray
r
=
getColumn
(
column
)
;
if
(
toPut
instanceof
IComplexNDArray
)
{
IComplexNDArray
putComplex
=
(
IComplexNDArray
)
toPut
;
for
(
int
i
=
0
;
i
<
r
.
length
(
)
;
i
++
)
{
IComplexNumber
n
=
putComplex
.
getComplex
(
i
)
;
r
.
putScalar
(
i
,
n
)
;
}
}
else
{
for
(
int
i
=
0
;
i
<
r
.
length
(
)
;
i
++
)
r
.
putScalar
(
i
,
Nd4j
.
createDouble
(
toPut
.
getDouble
(
i
)
,
0
)
)
;
}
return
this
;
}

Insert a column in to this array
Will throw an exception if this
ndarray is not a matrix

@param column the column to insert
@param toPut  the array to put
@return this


@Override
    public IComplexNDArray sub(INDArray other, INDArray result) {
        return dup().subi(other, result);
    }

@ Override public IComplexNDArray sub ( INDArray other , INDArray result ) { return dup ( ) . subi ( other , result ) ; }

copy subtraction of two matrices

@param other  the second ndarray to subtract
@param result the result ndarray
@return the result of the subtraction


@Override
    public IComplexNDArray add(INDArray other, INDArray result) {
        return dup().addi(other, result);
    }

@ Override public IComplexNDArray add ( INDArray other , INDArray result ) { return dup ( ) . addi ( other , result ) ; }

copy addition of two matrices

@param other  the second ndarray to add
@param result the result ndarray
@return the result of the addition


@Override
    public IComplexNDArray subi(INDArray other, INDArray result) {
        IComplexNDArray cOther = (IComplexNDArray) other;
        IComplexNDArray cResult = (IComplexNDArray) result;

        if (other.isScalar())
            return subi(cOther.getComplex(0), result);

        if (result == this)
            Nd4j.getBlasWrapper().axpy(Nd4j.NEG_UNIT, cOther, cResult);
        else if (result == other) {
            if (data.dataType() == (DataBuffer.Type.DOUBLE)) {
                Nd4j.getBlasWrapper().scal(Nd4j.NEG_UNIT.asDouble(), cResult);
                Nd4j.getBlasWrapper().axpy(Nd4j.UNIT, this, cResult);
            } else {
                Nd4j.getBlasWrapper().scal(Nd4j.NEG_UNIT.asFloat(), cResult);
                Nd4j.getBlasWrapper().axpy(Nd4j.UNIT, this, cResult);
            }

        } else {
            Nd4j.getBlasWrapper().copy(this, result);
            Nd4j.getBlasWrapper().axpy(Nd4j.NEG_UNIT, cOther, cResult);
        }
        return cResult;
    }

@ Override public IComplexNDArray subi ( INDArray other , INDArray result ) { IComplexNDArray cOther = ( IComplexNDArray ) other ; IComplexNDArray cResult = ( IComplexNDArray ) result ; if ( other . isScalar ( ) ) return subi ( cOther . getComplex ( 0 ) , result ) ; if ( result == this ) Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . NEG_UNIT , cOther , cResult ) ; else if ( result == other ) { if ( data . dataType ( ) == ( DataBuffer . Type . DOUBLE ) ) { Nd4j . getBlasWrapper ( ) . scal ( Nd4j . NEG_UNIT . asDouble ( ) , cResult ) ; Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . UNIT , this , cResult ) ; } else { Nd4j . getBlasWrapper ( ) . scal ( Nd4j . NEG_UNIT . asFloat ( ) , cResult ) ; Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . UNIT , this , cResult ) ; } } else { Nd4j . getBlasWrapper ( ) . copy ( this , result ) ; Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . NEG_UNIT , cOther , cResult ) ; } return cResult ; }

in place subtraction of two matrices

@param other  the second ndarray to subtract
@param result the result ndarray
@return the result of the subtraction


@Override
    public IComplexNDArray addi(INDArray other, INDArray result) {
        IComplexNDArray cOther = (IComplexNDArray) other;
        IComplexNDArray cResult = (IComplexNDArray) result;

        if (cOther.isScalar()) {
            return cResult.addi(cOther.getComplex(0), result);
        }
        if (isScalar()) {
            return cOther.addi(getComplex(0), result);
        }

        if (result == this) {

            Nd4j.getBlasWrapper().axpy(Nd4j.UNIT, cOther, cResult);
        } else if (result == other) {
            Nd4j.getBlasWrapper().axpy(Nd4j.UNIT, this, cResult);
        } else {
            INDArray resultLinear = result.linearView();
            INDArray otherLinear = other.linearView();
            INDArray linear = linearView();
            for (int i = 0; i < resultLinear.length(); i++) {
                resultLinear.putScalar(i, otherLinear.getDouble(i) + linear.getDouble(i));
            }

        }

        return (IComplexNDArray) result;
    }

@ Override public IComplexNDArray addi ( INDArray other , INDArray result ) { IComplexNDArray cOther = ( IComplexNDArray ) other ; IComplexNDArray cResult = ( IComplexNDArray ) result ; if ( cOther . isScalar ( ) ) { return cResult . addi ( cOther . getComplex ( 0 ) , result ) ; } if ( isScalar ( ) ) { return cOther . addi ( getComplex ( 0 ) , result ) ; } if ( result == this ) { Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . UNIT , cOther , cResult ) ; } else if ( result == other ) { Nd4j . getBlasWrapper ( ) . axpy ( Nd4j . UNIT , this , cResult ) ; } else { INDArray resultLinear = result . linearView ( ) ; INDArray otherLinear = other . linearView ( ) ; INDArray linear = linearView ( ) ; for ( int i = 0 ; i < resultLinear . length ( ) ; i ++ ) { resultLinear . putScalar ( i , otherLinear . getDouble ( i ) + linear . getDouble ( i ) ) ; } } return ( IComplexNDArray ) result ; }

in place addition of two matrices

@param other  the second ndarray to add
@param result the result ndarray
@return the result of the addition


@Override
    public IComplexNDArray assign(Number value) {
        IComplexNDArray one = linearView();
        for (int i = 0; i < one.length(); i++)
            one.putScalar(i, Nd4j.createDouble(value.doubleValue(), 0));
        return this;
    }

@ Override public IComplexNDArray assign ( Number value ) { IComplexNDArray one = linearView ( ) ; for ( int i = 0 ; i < one . length ( ) ; i ++ ) one . putScalar ( i , Nd4j . createDouble ( value . doubleValue ( ) , 0 ) ) ; return this ; }

Set the value of the ndarray to the specified value

@param value the value to assign
@return the ndarray with the values


@Override
    public IComplexNDArray ravel() {

        if (length() >= Integer.MAX_VALUE)
            throw new IllegalArgumentException("length() can not be >= Integer.MAX_VALUE");
        IComplexNDArray ret = Nd4j.createComplex((int) length(), ordering());
        IComplexNDArray linear = linearView();
        for (int i = 0; i < length(); i++) {
            ret.putScalar(i, linear.getComplex(i));
        }

        return ret;

    }

Flattens the array for linear indexing

@return the flattened version of this array


public static IComplexNDArray eigenvalues(INDArray A) {
        assert A.rows() == A.columns();
        INDArray WR = Nd4j.create(A.rows(), A.rows());
        INDArray WI = WR.dup();
        Nd4j.getBlasWrapper().geev('N', 'N', A.dup(), WR, WI, dummy, dummy);
        return Nd4j.createComplex(WR, WI);
    }

public static IComplexNDArray eigenvalues ( INDArray A ) { assert A . rows ( ) == A . columns ( ) ; INDArray WR = Nd4j . create ( A . rows ( ) , A . rows ( ) ) ; INDArray WI = WR . dup ( ) ; Nd4j . getBlasWrapper ( ) . geev ( ' ' , ' ' , A . dup ( ) , WR , WI , dummy , dummy ) ; return Nd4j . createComplex ( WR , WI ) ; }

Computes the eigenvalues of a general matrix.

Computes the eigenvalues of a general matrix .


public static INDArray symmetricGeneralizedEigenvalues(INDArray A, INDArray B) {
        assert A.rows() == A.columns();
        assert B.rows() == B.columns();
        INDArray W = Nd4j.create(A.rows());

        A = InvertMatrix.invert(B, false).mmuli(A);
        Nd4j.getBlasWrapper().syev('V', 'L', A, W);
        return W;
    }

public static INDArray symmetricGeneralizedEigenvalues ( INDArray A , INDArray B ) { assert A . rows ( ) == A . columns ( ) ; assert B . rows ( ) == B . columns ( ) ; INDArray W = Nd4j . create ( A . rows ( ) ) ; A = InvertMatrix . invert ( B , false ) . mmuli ( A ) ; Nd4j . getBlasWrapper ( ) . syev ( ' ' , ' ' , A , W ) ; return W ; }

Compute generalized eigenvalues of the problem A x = L B x.
The data will be unchanged, no eigenvectors returned.

@param A symmetric Matrix A.
@param B symmetric Matrix B.
@return a vector of eigenvalues L.

Compute generalized eigenvalues of the problem A x = L B x . The data will be unchanged no eigenvectors returned .


@Override
    public int iamax(IComplexNDArray arr) {
        if (arr.data().dataType() == DataBuffer.Type.DOUBLE)
            return izamax(arr.length(), arr, BlasBufferUtil.getBlasStride(arr));
        return icamax(arr.length(), arr, BlasBufferUtil.getBlasStride(arr));
    }

@ Override public int iamax ( IComplexNDArray arr ) { if ( arr . data ( ) . dataType ( ) == DataBuffer . Type . DOUBLE ) return izamax ( arr . length ( ) , arr , BlasBufferUtil . getBlasStride ( arr ) ) ; return icamax ( arr . length ( ) , arr , BlasBufferUtil . getBlasStride ( arr ) ) ; }

finds the element of a vector that has the largest absolute value.

@param arr
@return

finds the element of a vector that has the largest absolute value .


@Override
    public void copy(IComplexNDArray x, IComplexNDArray y) {
        if (x.data().dataType() == DataBuffer.Type.DOUBLE)
            zcopy(x.length(), x, BlasBufferUtil.getBlasStride(x), y, BlasBufferUtil.getBlasStride(y));
        else
            ccopy(x.length(), x, BlasBufferUtil.getBlasStride(x), y, BlasBufferUtil.getBlasStride(y));
    }

@ Override public void copy ( IComplexNDArray x , IComplexNDArray y ) { if ( x . data ( ) . dataType ( ) == DataBuffer . Type . DOUBLE ) zcopy ( x . length ( ) , x , BlasBufferUtil . getBlasStride ( x ) , y , BlasBufferUtil . getBlasStride ( y ) ) ; else ccopy ( x . length ( ) , x , BlasBufferUtil . getBlasStride ( x ) , y , BlasBufferUtil . getBlasStride ( y ) ) ; }

copy a vector to another vector.

@param x
@param y


@Override
    public void scal(long N, IComplexNumber alpha, IComplexNDArray X) {
        if (X.data().dataType() == DataBuffer.Type.DOUBLE)
            zscal(N, alpha.asDouble(), X, BlasBufferUtil.getBlasStride(X));
        else
            cscal(N, alpha.asFloat(), X, BlasBufferUtil.getBlasStride(X));

    }

@ Override public void scal ( long N , IComplexNumber alpha , IComplexNDArray X ) { if ( X . data ( ) . dataType ( ) == DataBuffer . Type . DOUBLE ) zscal ( N , alpha . asDouble ( ) , X , BlasBufferUtil . getBlasStride ( X ) ) ; else cscal ( N , alpha . asFloat ( ) , X , BlasBufferUtil . getBlasStride ( X ) ) ; }

computes a vector by a scalar product.

@param N
@param alpha
@param X


@Override
    public void processMessage() {
        // this only picks up new training round
        //log.info("sI_{} Processing DistributedSgDotMessage taskId: {}", transport.getShardIndex(), getTaskId());

        SkipGramRequestMessage sgrm = new SkipGramRequestMessage(w1, w2, rowsB, codes, negSamples, alpha, 119);
        if (negSamples > 0) {
            // unfortunately we have to get copy of negSamples here
            int negatives[] = Arrays.copyOfRange(rowsB, codes.length, rowsB.length);
            sgrm.setNegatives(negatives);
        }
        sgrm.setTaskId(this.taskId);
        sgrm.setOriginatorId(this.getOriginatorId());

        // FIXME: get rid of THAT
        SkipGramTrainer sgt = (SkipGramTrainer) trainer;
        sgt.pickTraining(sgrm);

        //TODO: make this thing a single op, even specialOp is ok
        // we calculate dot for all involved rows

        int resultLength = codes.length + (negSamples > 0 ? (negSamples + 1) : 0);

        INDArray result = Nd4j.createUninitialized(resultLength, 1);
        int e = 0;
        for (; e < codes.length; e++) {
            double dot = Nd4j.getBlasWrapper().dot(storage.getArray(WordVectorStorage.SYN_0).getRow(w2),
                            storage.getArray(WordVectorStorage.SYN_1).getRow(rowsB[e]));
            result.putScalar(e, dot);
        }

        // negSampling round
        for (; e < resultLength; e++) {
            double dot = Nd4j.getBlasWrapper().dot(storage.getArray(WordVectorStorage.SYN_0).getRow(w2),
                            storage.getArray(WordVectorStorage.SYN_1_NEGATIVE).getRow(rowsB[e]));
            result.putScalar(e, dot);
        }

        if (voidConfiguration.getExecutionMode() == ExecutionMode.AVERAGING) {
            // just local bypass
            DotAggregation dot = new DotAggregation(taskId, (short) 1, shardIndex, result);
            dot.setTargetId((short) -1);
            dot.setOriginatorId(getOriginatorId());
            transport.putMessage(dot);
        } else if (voidConfiguration.getExecutionMode() == ExecutionMode.SHARDED) {
            // send this message to everyone
            DotAggregation dot = new DotAggregation(taskId, (short) voidConfiguration.getNumberOfShards(), shardIndex,
                            result);
            dot.setTargetId((short) -1);
            dot.setOriginatorId(getOriginatorId());
            transport.sendMessage(dot);
        }
    }

This method calculates dot of gives rows


private static SDVariable nonZeroCount(SDVariable weights, SDVariable labels){
        SameDiff sd = weights.getSameDiff();

        SDVariable present = sd.neq(weights, 0.0);
        SDVariable presentBroadcast = sd.zerosLike(labels).add(present);

        return sd.sum(presentBroadcast);
    }

private static SDVariable nonZeroCount ( SDVariable weights , SDVariable labels ) { SameDiff sd = weights . getSameDiff ( ) ; SDVariable present = sd . neq ( weights , 0.0 ) ; SDVariable presentBroadcast = sd . zerosLike ( labels ) . add ( present ) ; return sd . sum ( presentBroadcast ) ; }

Determine the number of weight entries that are non-zero, after broadcasting

@param weights
@param labels
@return

Determine the number of weight entries that are non - zero after broadcasting


private static LossInfo doReduce(SameDiff sd, String outputName, boolean isMean, LossInfo.Builder b, Reduction reduction,
                          SDVariable preReduceLoss, SDVariable label, SDVariable weights, int[] dimensions){
        switch (reduction){
            case NONE:
                //Return same shape as predictions/labels
                b.loss(preReduceLoss);
                break;
            case SPECIFIED_DIMS:
                //Reduce along specified dimensions
                if(isMean){
                    //Example: MSE + mean along examples
                    b.loss(sd.mean(outputName, preReduceLoss, dimensions));
                } else {
                    //Example: L1 loss (sum) + mean along examples
                    b.loss(sd.sum(outputName, preReduceLoss, dimensions));
                }
            case SUM:
                if(isMean){
                    //Example: MSE (mean) + sum along examples
                    SDVariable m = sd.mean(preReduceLoss, dimensions);
                    b.loss(sd.sum(outputName, m));
                } else {
                    //Example: L1 loss (sum) + sum along examples -> sum along all dimensions
                    b.loss(sd.sum(outputName, preReduceLoss));
                }
                break;
            case MEAN_BY_WEIGHT:
                SDVariable weightSum = sd.sum(weights);
                if(isMean){
                    //Example: MSE (mean) + mean by weights over examples
                    //reduce along dims + reduce along remaining dims == reduce along *all* dims
                    SDVariable m2 = sd.mean(preReduceLoss);
                    b.loss(m2.div(outputName, weightSum));
                } else {
                    //Example: L1 (sum) + mean by weights over examples
                    SDVariable sum = sd.sum(preReduceLoss, dimensions);
                    b.loss(sum.div(outputName, weightSum));
                }
                break;
            case MEAN_BY_COUNT:
                SDVariable nonZeroWeights = nonZeroCount(weights, label);
                SDVariable r;
                if(isMean){
                    //Example: MSE (mean) + mean by count over examples
                    r = sd.sum(preReduceLoss);
                } else {
                    //Example: L1 (sum) + mean by count over examples
                    SDVariable sum = sd.sum(preReduceLoss, dimensions);
                    r = sd.mean(sum);
                }
                b.loss(r.div(outputName, nonZeroWeights));
                break;
            default:
                throw new RuntimeException("Unknown reduction: " + reduction);
        }

        return b.build();
    }

Perform the final reduction on the loss function

@param sd
@param outputName
@param isMean
@param b
@param reduction
@param preReduceLoss
@param label
@param weights
@param dimensions
@return


public static <T> Constructor<T> getNoArgConstructor(Class<T> clazz) {
		try {
			Constructor<T> ctor = clazz.getDeclaredConstructor(new Class[0]);
			ctor.setAccessible(true);
			return ctor;
		}
		catch (NoSuchMethodException e) {
			// lame there is no way to tell if the class is a nonstatic inner class
			if (clazz.isMemberClass() || clazz.isAnonymousClass() || clazz.isLocalClass())
				throw new IllegalStateException(clazz.getName() + " must be static and must have a no-arg constructor", e);
			else
				throw new IllegalStateException(clazz.getName() + " must have a no-arg constructor", e);
		}
	}

Throw an IllegalStateException if the class does not have a no-arg constructor.

Throw an IllegalStateException if the class does not have a no - arg constructor .


public static MethodHandle getConstructor(Class<?> clazz, Class<?>... args) {
		try {
			// We use unreflect so that we can make the constructor accessible
			Constructor<?> ctor = clazz.getDeclaredConstructor(args);
			ctor.setAccessible(true);
			return MethodHandles.lookup().unreflectConstructor(ctor);
		}
		catch (NoSuchMethodException e) {
			throw new IllegalStateException(clazz.getName() + " has no constructor with args " + Arrays.toString(args), e);
		} catch (IllegalAccessException e) {
			throw new IllegalStateException("Problem getting constructor for " + clazz.getName() + " with args " + Arrays.toString(args), e);
		}
	}

Gets a constructor that has the specified types of arguments.
Throw an IllegalStateException if the class does not have such a constructor.

Gets a constructor that has the specified types of arguments . Throw an IllegalStateException if the class does not have such a constructor .


public static <T> T invoke(MethodHandle methodHandle, Object... params) {
		try {
			return (T)methodHandle.invokeWithArguments(params);
		} catch (RuntimeException e) {
			throw e;
		} catch (Throwable throwable) {
			throw new RuntimeException(throwable);
		}
	}

public static < T > T invoke ( MethodHandle methodHandle , Object ... params ) { try { return ( T ) methodHandle . invokeWithArguments ( params ) ; } catch ( RuntimeException e ) { throw e ; } catch ( Throwable throwable ) { throw new RuntimeException ( throwable ) ; } }

Wraps any non-runtime exceptions with a runtime exception

Wraps any non - runtime exceptions with a runtime exception


@SuppressWarnings("unchecked")
	public static <A extends Annotation> A getAnnotation(Annotation[] annotations, Class<A> annotationType) {
		for (Annotation anno: annotations)
			if (annotationType.isAssignableFrom(anno.getClass()))
				return (A)anno;

		return null;
	}

@ SuppressWarnings ( "unchecked" ) public static < A extends Annotation > A getAnnotation ( Annotation [ ] annotations , Class < A > annotationType ) { for ( Annotation anno : annotations ) if ( annotationType . isAssignableFrom ( anno . getClass ( ) ) ) return ( A ) anno ; return null ; }

Gets the annotation that has the specified type, or null if there isn't one

Gets the annotation that has the specified type or null if there isn t one


public static <A extends Annotation> A getDeclaredAnnotation(Class<?> onClass, Class<A> annotationType) {
		return getAnnotation(onClass.getDeclaredAnnotations(), annotationType);
	}

public static < A extends Annotation > A getDeclaredAnnotation ( Class < ? > onClass , Class < A > annotationType ) { return getAnnotation ( onClass . getDeclaredAnnotations ( ) , annotationType ) ; }

Get the declared annotation, ignoring any inherited annotations

Get the declared annotation ignoring any inherited annotations


public static <A extends Annotation> boolean isDeclaredAnnotationPresent(Class<?> onClass, Class<A> annotationType) {
		return getDeclaredAnnotation(onClass, annotationType) != null;
	}

public static < A extends Annotation > boolean isDeclaredAnnotationPresent ( Class < ? > onClass , Class < A > annotationType ) { return getDeclaredAnnotation ( onClass , annotationType ) != null ; }

Is the declared annotation present, ignoring any inherited annotations

Is the declared annotation present ignoring any inherited annotations


@SuppressWarnings("unchecked")
	public static <S> S create(Class<? super S> interf, Result<S> result) {
		return (S)Proxy.newProxyInstance(result.getClass().getClassLoader(), new Class[] { interf }, new ResultProxy<>(result));
	}

@ SuppressWarnings ( "unchecked" ) public static < S > S create ( Class < ? super S > interf , Result < S > result ) { return ( S ) Proxy . newProxyInstance ( result . getClass ( ) . getClassLoader ( ) , new Class [ ] { interf } , new ResultProxy <> ( result ) ) ; }

Create a ResultProxy for the given interface.

Create a ResultProxy for the given interface .


public P load(final BaseEntity<?> ent, final LoadContext ctx) {
		try {
			// The context needs to know the root entity for any given point
			ctx.setCurrentRoot(Key.create((com.google.cloud.datastore.Key)ent.getKey()));

			final EntityValue entityValue = makeLoadEntityValue(ent);
			return translator.load(entityValue, ctx, Path.root());
		}
		catch (LoadException ex) { throw ex; }
		catch (Exception ex) {
			throw new LoadException(ent, ex.getMessage(), ex);
		}
	}

Converts an entity to an object of the appropriate type for this metadata structure.
Does not check that the entity is appropriate; that should be done when choosing
which EntityMetadata to call.

Converts an entity to an object of the appropriate type for this metadata structure . Does not check that the entity is appropriate ; that should be done when choosing which EntityMetadata to call .


public FullEntity<?> save(final P pojo, final SaveContext ctx) {
		try {
			return translator.save(pojo, false, ctx, Path.root()).get();
		}
		catch (SaveException ex) { throw ex; }
		catch (Exception ex) {
			throw new SaveException(pojo, ex);
		}
	}

public FullEntity < ? > save ( final P pojo , final SaveContext ctx ) { try { return translator . save ( pojo , false , ctx , Path . root ( ) ) . get ( ) ; } catch ( SaveException ex ) { throw ex ; } catch ( Exception ex ) { throw new SaveException ( pojo , ex ) ; } }

Converts an object to a datastore Entity with the appropriate Key type.

Converts an object to a datastore Entity with the appropriate Key type .


public static MemcacheService createProxy(final MemcacheService raw, final int retryCount) {
		return (MemcacheService)java.lang.reflect.Proxy.newProxyInstance(
			raw.getClass().getClassLoader(),
			raw.getClass().getInterfaces(),
			new MemcacheServiceRetryProxy(raw, retryCount));
	}

public static MemcacheService createProxy ( final MemcacheService raw , final int retryCount ) { return ( MemcacheService ) java . lang . reflect . Proxy . newProxyInstance ( raw . getClass ( ) . getClassLoader ( ) , raw . getClass ( ) . getInterfaces ( ) , new MemcacheServiceRetryProxy ( raw , retryCount ) ) ; }

Create the proxy that does retries. Adds a strict error handler to the service.

Create the proxy that does retries . Adds a strict error handler to the service .


public <T> EntityMetadata<T> getMetadataSafe(String kind) throws IllegalArgumentException {
		EntityMetadata<T> metadata = this.getMetadata(kind);
		if (metadata == null)
			throw new IllegalArgumentException("No entity class has been registered which matches kind '" + kind + "'");
		else
			return metadata;
	}

Gets metadata for the specified kind
@throws IllegalArgumentException if the kind has not been registered


public <T> QueryResults<Key<T>> queryKeysOnly(final KeyQuery query) {
		log.trace("Starting keys-only query");

		return new KeyQueryResults<>(ds.run(query));
	}

public
<
T
>
QueryResults
<
Key
<
T
>
>
queryKeysOnly
(
final
KeyQuery
query
)
{
log
.
trace
(
"Starting keys-only query"
)
;
return
new
KeyQueryResults
<>
(
ds
.
run
(
query
)
)
;
}


public <T> QueryResults<T> queryHybrid(final KeyQuery query, final int chunkSize) {
		log.trace("Starting hybrid query");

		final QueryResults<Key<T>> results = new KeyQueryResults<>(ds.run(query));

		return new HybridQueryResults<>(loader.createLoadEngine(), results, chunkSize);
	}

public
<
T
>
QueryResults
<
T
>
queryHybrid
(
final
KeyQuery
query
,
final
int
chunkSize
)
{
log
.
trace
(
"Starting hybrid query"
)
;
final
QueryResults
<
Key
<
T
>
>
results
=
new
KeyQueryResults
<>
(
ds
.
run
(
query
)
)
;
return
new
HybridQueryResults
<>
(
loader
.
createLoadEngine
(
)
,
results
,
chunkSize
)
;
}


public <T> QueryResults<T> queryNormal(final EntityQuery query, final int chunkSize) {
		log.trace("Starting normal query");

		// Normal queries are actually more complex than hybrid queries because we need the fetched entities to
		// be stuffed back into the engine to satisfy @Load instructions without extra fetching. Even though
		// this looks like we're doing hybrid load-by-key operations, the data is pulled from the stuffed values.

		final LoadEngine loadEngine = loader.createLoadEngine();

		final QueryResults<Entity> entityResults = ds.run(query);

		final QueryResults<com.google.cloud.datastore.Key> stuffed = new StuffingQueryResults(loadEngine, entityResults);

		final QueryResults<Key<T>> keyResults = new KeyQueryResults<>(stuffed);

		return new HybridQueryResults<>(loadEngine, keyResults, chunkSize);
	}


public <T> QueryResults<T> queryProjection(final ProjectionEntityQuery query) {
		log.trace("Starting projection query");

		final LoadEngine loadEngine = loader.createLoadEngine();

		return new ProjectionQueryResults<>(ds.run(query), loadEngine);
	}

public
<
T
>
QueryResults
<
T
>
queryProjection
(
final
ProjectionEntityQuery
query
)
{
log
.
trace
(
"Starting projection query"
)
;
final
LoadEngine
loadEngine
=
loader
.
createLoadEngine
(
)
;
return
new
ProjectionQueryResults
<>
(
ds
.
run
(
query
)
,
loadEngine
)
;
}

A projection query. Bypasses the session entirely.

A projection query . Bypasses the session entirely .


public int queryCount(final KeyQuery query) {
		log.trace("Starting count query");

		final QueryResults<com.google.cloud.datastore.Key> results = ds.run(query);
		return Iterators.size(results);
	}

public
int
queryCount
(
final
KeyQuery
query
)
{
log
.
trace
(
"Starting count query"
)
;
final
QueryResults
<
com
.
google
.
cloud
.
datastore
.
Key
>
results
=
ds
.
run
(
query
)
;
return
Iterators
.
size
(
results
)
;
}

The fundamental query count operation. This doesn't appear to be implemented in the new SDK, so we simulate
with a keys-only query.

The fundamental query count operation . This doesn t appear to be implemented in the new SDK so we simulate with a keys - only query .


private <T> Iterator<Iterator<T>> safePartition(final Iterator<T> input, int chunkSize) {
		// Cloud Datastore library errors if you try to fetch more than 1000 keys at a time
		if (chunkSize > 1000) {
			chunkSize = 1000;
		}
		return Iterators.transform(Iterators.partition(input, chunkSize), IterateFunction.instance());
	}

Detects Integer.MAX_VALUE and prevents OOM exceptions

Detects Integer . MAX_VALUE and prevents OOM exceptions


private Iterator<ResultWithCursor<T>> load(final Iterator<ResultWithCursor<Key<T>>> keys) {
		final List<Entry<ResultWithCursor<Key<T>>, Result<T>>> results = Lists.newArrayList();

		while (keys.hasNext()) {
			final ResultWithCursor<Key<T>> next = keys.next();
			results.add(Maps.immutableEntry(next, loadEngine.load(next.getResult())));
		}

		loadEngine.execute();

		return Iterators.transform(results.iterator(), entry -> new ResultWithCursor<>(entry.getValue().now(), entry.getKey().getCursorAfter()));
	}

private Iterator < ResultWithCursor < T > > load ( final Iterator < ResultWithCursor < Key < T > > > keys ) { final List < Entry < ResultWithCursor < Key < T > > , Result < T > > > results = Lists . newArrayList ( ) ; while ( keys . hasNext ( ) ) { final ResultWithCursor < Key < T > > next = keys . next ( ) ; results . add ( Maps . immutableEntry ( next , loadEngine . load ( next . getResult ( ) ) ) ) ; } loadEngine . execute ( ) ; return Iterators . transform ( results . iterator ( ) , entry -> new ResultWithCursor <> ( entry . getValue ( ) . now ( ) , entry . getKey ( ) . getCursorAfter ( ) ) ) ; }

Loads them; note that it's possible for some loaded results to be null

Loads them ; note that it s possible for some loaded results to be null


public static String msg(Path path, String msg) {
		StringBuilder bld = new StringBuilder();
		bld.append("\t.");
		bld.append(path.toPathString());

		if (bld.length() < PATH_PADDING)
			while (bld.length() < PATH_PADDING)
				bld.append(' ');
		else
			bld.append('\t');

		bld.append(msg);

		return bld.toString();
	}

public static String msg ( Path path , String msg ) { StringBuilder bld = new StringBuilder ( ) ; bld . append ( "\t." ) ; bld . append ( path . toPathString ( ) ) ; if ( bld . length ( ) < PATH_PADDING ) while ( bld . length ( ) < PATH_PADDING ) bld . append ( ' ' ) ; else bld . append ( ' ' ) ; bld . append ( msg ) ; return bld . toString ( ) ; }


public static <T> Key<T> create(final T pojo) {
		return ObjectifyService.factory().keys().keyOf(pojo);
	}

public static < T > Key < T > create ( final T pojo ) { return ObjectifyService . factory ( ) . keys ( ) . keyOf ( pojo ) ; }

Create a key from a registered POJO entity.

Create a key from a registered POJO entity .


private int compareToWithIdentityHash(final Object k1, final Object k2) {
		return Integer.compare(System.identityHashCode(k1), System.identityHashCode(k2));
	}

private int compareToWithIdentityHash ( final Object k1 , final Object k2 ) { return Integer . compare ( System . identityHashCode ( k1 ) , System . identityHashCode ( k2 ) ) ; }

I have no idea what this is about, it was in the old logic

I have no idea what this is about it was in the old logic


public static <V> Key<V> key(final com.google.cloud.datastore.Key raw) {
		if (raw == null)
			return null;
		else
			return new Key<>(raw);
	}

public static < V > Key < V > key ( final com . google . cloud . datastore . Key raw ) { if ( raw == null ) return null ; else return new Key <> ( raw ) ; }

Easy null-safe conversion of the raw key.

Easy null - safe conversion of the raw key .


public static com.google.cloud.datastore.Key key(final Key<?> typed) {
		if (typed == null)
			return null;
		else
			return typed.getRaw();
	}

public static com . google . cloud . datastore . Key key ( final Key < ? > typed ) { if ( typed == null ) return null ; else return typed . getRaw ( ) ; }

Easy null-safe conversion of the typed key.

Easy null - safe conversion of the typed key .


private static String getKindHere(final Class<?> clazz) {
		// @Entity is inherited so we have to be explicit about the declared annotations
		final Entity ourAnn = TypeUtils.getDeclaredAnnotation(clazz, Entity.class);
		if (ourAnn != null)
			if (ourAnn.name().length() != 0)
				return ourAnn.name();
			else
				return clazz.getSimpleName();

		return null;
	}

Get the kind from the class if the class has an @Entity annotation, otherwise return null.


static boolean isMissingTypeParameters(Type type) {
		if (type instanceof Class) {
			for (Class<?> clazz = (Class<?>) type; clazz != null; clazz = clazz.getEnclosingClass()) {
				if (clazz.getTypeParameters().length != 0)
					return true;
			}
			return false;
		} else if (type instanceof ParameterizedType) {
			return false;
		} else {
			throw new AssertionError("Unexpected type " + type.getClass());
		}
	}

static
boolean
isMissingTypeParameters
(
Type
type
)
{
if
(
type
instanceof
Class
)
{
for
(
Class
<
>
clazz
=
(
Class
<
>
)
type
;
clazz
!=
;
clazz
=
clazz
.
getEnclosingClass
(
)
)
{
if
(
clazz
.
getTypeParameters
(
)
.
length
!=
0
)
return
true
;
}
return
false
;
}
else
if
(
type
instanceof
ParameterizedType
)
{
return
false
;
}
else
{
throw
new
AssertionError
(
"Unexpected type "
+
type
.
getClass
(
)
)
;
}
}

Checks if the given type is a class that is supposed to have type parameters, but doesn't.
In other words, if it's a really raw type.

Checks if the given type is a class that is supposed to have type parameters but doesn t . In other words if it s a really raw type .


public static boolean isSuperType(Type superType, Type subType) {
		if (superType instanceof ParameterizedType || superType instanceof Class || superType instanceof GenericArrayType) {
			Class<?> superClass = erase(superType);
			Type mappedSubType = getExactSuperType(capture(subType), superClass);
			if (mappedSubType == null) {
				return false;
			} else if (superType instanceof Class<?>) {
				return true;
			} else if (mappedSubType instanceof Class<?>) {
				// TODO treat supertype by being raw type differently ("supertype, but with warnings")
				return true; // class has no parameters, or it's a raw type
			} else if (mappedSubType instanceof GenericArrayType) {
				Type superComponentType = getArrayComponentType(superType);
				assert superComponentType != null;
				Type mappedSubComponentType = getArrayComponentType(mappedSubType);
				assert mappedSubComponentType != null;
				return isSuperType(superComponentType, mappedSubComponentType);
			} else {
				assert mappedSubType instanceof ParameterizedType;
				ParameterizedType pMappedSubType = (ParameterizedType) mappedSubType;
				assert pMappedSubType.getRawType() == superClass;
				ParameterizedType pSuperType = (ParameterizedType)superType;

				Type[] superTypeArgs = pSuperType.getActualTypeArguments();
				Type[] subTypeArgs = pMappedSubType.getActualTypeArguments();
				assert superTypeArgs.length == subTypeArgs.length;
				for (int i = 0; i < superTypeArgs.length; i++) {
					if (! contains(superTypeArgs[i], subTypeArgs[i])) {
						return false;
					}
				}
				// params of the class itself match, so if the owner types are supertypes too, it's a supertype.
				return pSuperType.getOwnerType() == null || isSuperType(pSuperType.getOwnerType(), pMappedSubType.getOwnerType());
			}
		} else if (superType instanceof CaptureType) {
			if (superType.equals(subType))
				return true;
			for (Type lowerBound : ((CaptureType) superType).getLowerBounds()) {
				if (isSuperType(lowerBound, subType)) {
					return true;
				}
			}
			return false;
		} else if (superType instanceof GenericArrayType) {
			return isArraySupertype(superType, subType);
		} else {
			throw new RuntimeException("not implemented: " + superType.getClass());
		}
	}

Checks if the capture of subType is a subtype of superType


private static Type[] getExactDirectSuperTypes(Type type) {
		if (type instanceof ParameterizedType || type instanceof Class) {
			Class<?> clazz;
			if (type instanceof ParameterizedType) {
				clazz = (Class<?>)((ParameterizedType)type).getRawType();
			} else {
				// TODO primitive types?
				clazz = (Class<?>)type;
				if (clazz.isArray())
					return getArrayExactDirectSuperTypes(clazz);
			}

			Type[] superInterfaces = clazz.getGenericInterfaces();
			Type superClass = clazz.getGenericSuperclass();

			// the only supertype of an interface without superinterfaces is Object
			if (superClass == null && superInterfaces.length == 0 && clazz.isInterface()) {
				return new Type[] {Object.class};
			}

			Type[] result;
			int resultIndex;
			if (superClass == null) {
				result = new Type[superInterfaces.length];
				resultIndex = 0;
			} else {
				result = new Type[superInterfaces.length + 1];
				resultIndex = 1;
				result[0] = mapTypeParameters(superClass, type);
			}
			for (Type superInterface : superInterfaces) {
				result[resultIndex++] = mapTypeParameters(superInterface, type);
			}

			return result;
		} else if (type instanceof TypeVariable) {
			TypeVariable<?> tv = (TypeVariable<?>) type;
			return tv.getBounds();
		} else if (type instanceof WildcardType) {
			// This should be a rare case: normally this wildcard is already captured.
			// But it does happen if the upper bound of a type variable contains a wildcard
			// TODO shouldn't upper bound of type variable have been captured too? (making this case impossible?)
			return ((WildcardType) type).getUpperBounds();
		} else if (type instanceof CaptureType) {
			return ((CaptureType)type).getUpperBounds();
		} else if (type instanceof GenericArrayType) {
			return getArrayExactDirectSuperTypes(type);
		} else if (type == null) {
			throw new NullPointerException();
		} else {
			throw new RuntimeException("not implemented type: " + type);
		}
	}

Returns the direct supertypes of the given type. Resolves type parameters.

Returns the direct supertypes of the given type . Resolves type parameters .


public static Type capture(Type type) {
		if (type instanceof ParameterizedType) {
			return capture((ParameterizedType)type);
		} else {
			return type;
		}
	}

public static Type capture ( Type type ) { if ( type instanceof ParameterizedType ) { return capture ( ( ParameterizedType ) type ) ; } else { return type ; } }

Applies capture conversion to the given type.

Applies capture conversion to the given type .


public <P, D> Translator<P, D> getTranslator(final TypeKey<P> tk, final CreateContext ctx, final Path path) {
		return factory.getTranslators().get(tk, ctx, path);
	}

public < P , D > Translator < P , D > getTranslator ( final TypeKey < P > tk , final CreateContext ctx , final Path path ) { return factory . getTranslators ( ) . get ( tk , ctx , path ) ; }

Get the relevant translator, creating it if necessary.

Get the relevant translator creating it if necessary .