docs: @Override
      public <T extends Aggregate> void exec(Batch<T> batch) {
          //profilingHookIn(batch);
  
          IntPointer pointer = (IntPointer) getPointer(batch);
  
          int maxTypes = 5;
  
          int maxIntArrays = batch.getSample().maxIntArrays();
  
          int maxArraySize = batch.getSample().maxIntArraySize();
  
  
          int indexPos = maxTypes * Batch.getBatchLimit();
          int intArraysPos = indexPos + (batch.getSample().maxIndexArguments() * Batch.getBatchLimit());
          int realPos = (intArraysPos + (maxIntArrays * maxArraySize * Batch.getBatchLimit()))
                  / (Nd4j.dataType() == DataType.DOUBLE ? 2 : 1);
          int argsPos = (realPos + ((batch.getSample().maxRealArguments() * Batch.getBatchLimit())))
                  / (Nd4j.dataType() == DataType.DOUBLE ? 1 : 2);
          int shapesPos = argsPos + (batch.getSample().maxArguments() * Batch.getBatchLimit());
          DataType dataType = null;
          for (int i = 0; i < batch.getNumAggregates(); i++) {
              T op = batch.getAggregates().get(i);
  
              if (i == 0)
                  dataType = op.getArguments().get(0).dataType();
  
              // put num arguments
              int idx = i * maxTypes;
              pointer.put(idx, op.getArguments().size());
              pointer.put(idx + 1, op.getShapes().size());
              pointer.put(idx + 2, op.getIndexingArguments().size());
              pointer.put(idx + 3, op.getRealArguments().size());
              pointer.put(idx + 4, op.getIntArrayArguments().size());
  
  
              // putting indexing arguments
              for (int e = 0; e < op.getIndexingArguments().size(); e++) {
                  idx = indexPos + i * batch.getSample().maxIndexArguments();
                  pointer.put(idx + e, op.getIndexingArguments().get(e));
              }
  
              // putting intArray values
              int bsize = maxIntArrays * maxArraySize;
              for (int e = 0; e < op.getIntArrayArguments().size(); e++) {
                  int step = (i * bsize) + (e * maxArraySize);
                  if (op.getIntArrayArguments().get(e) != null)
                      for (int x = 0; x < op.getIntArrayArguments().get(e).length; x++) {
                          idx = intArraysPos + step + x;
                          pointer.put(idx, op.getIntArrayArguments().get(e)[x]);
                      }
              }
  
              // TODO: variable datatype should be handled here
              // putting real arguments
  
              switch (dataType){
                  case FLOAT:
                      FloatPointer fPtr = new FloatPointer(pointer);
                      for (int e = 0; e < op.getRealArguments().size(); e++) {
                          idx = realPos + i * op.maxRealArguments();
                          fPtr.put(idx + e, op.getRealArguments().get(e).floatValue());
                      }
                      break;
                  case DOUBLE:
                      DoublePointer dPtr = new DoublePointer(pointer);
                      for (int e = 0; e < op.getRealArguments().size(); e++) {
                          idx = realPos + (i * op.maxRealArguments());
                          dPtr.put(idx + e, op.getRealArguments().get(e).doubleValue());
                      }
                      break;
                  default:
                      throw new ND4JIllegalArgumentException("Only FLOAT and DOUBLE datatypes are supported");
              }
  
              if (extraz.get() == null)
                  extraz.set(new PointerPointer(32));
  
              // putting arguments pointers
  
              PointerPointer ptrPtr = new PointerPointer(pointer);//extraz.get().put(pointer);
  
              for (int e = 0; e < op.getArguments().size(); e++) {
                  idx = argsPos + i * batch.getSample().maxArguments();
  
                  if (op.getArguments().get(e) != null) {
                      ptrPtr.put(idx + e, op.getArguments().get(e).data().addressPointer());
                  }
              }
  
  
              // putting shape pointers
              for (int e = 0; e < op.getShapes().size(); e++) {
                  idx = shapesPos + i * batch.getSample().maxShapes();
  
                  if (op.getShapes().get(e) != null)
                      ptrPtr.put(idx + e, op.getShapes().get(e).addressPointer());
              }
          }
  
          loop.execAggregateBatch(null, batch.getNumAggregates(), batch.opNum(),
                      batch.getSample().maxArguments(), batch.getSample().maxShapes(),
                      batch.getSample().maxIntArrays(), batch.getSample().maxIntArraySize(),
                      batch.getSample().maxIndexArguments(), batch.getSample().maxRealArguments(), pointer, FlatBuffersMapper.getDataTypeAsByte(dataType));
  
      }