# Path: dlearn/data/hidata.py
# class HierarData(object):
# 
#     def __init__(self, data, limit=None):
#         self._cpu_data = data
# 
#         if limit is None or limit > data.shape[0]:
#             limit = data.shape[0]
#         self._limit = limit
# 
#         self._gpu_data = create_shared(self._cpu_data[0:limit])
#         self._cur_irange = create_shared(np.asarray([0, limit]))
# 
#     def prepare(self, irange):
#         l, r = irange
#         cur_l, cur_r = self._cur_irange.get_value(borrow=True)
# 
#         if min(l, r - 1) < cur_l or max(l, r - 1) >= cur_r:
#             self._cur_irange.set_value(np.asarray([l, l + self._limit]))
#             self._gpu_data.set_value(
#                 self._cpu_data[l:l + self._limit], borrow=True)
# 
#     @property
#     def cur_irange(self):
#         return self._cur_irange
# 
#     @property
#     def cpu_data(self):
#         return self._cpu_data
# 
#     @property
#     def gpu_data(self):
#         return self._gpu_data
# 
# Path: dlearn/utils/math.py
# def create_shared(x):
# def create_empty(p):
# def dropout(x, ratio):


import numpy as np
from .hidata import HierarData
from ..utils.math import nprng


def _get_n(data):
    return data[0].shape[0] if isinstance(data, list) else data.shape[0]


def _combine(*args):
    if isinstance(args[0], list):
        data = []
        for j in xrange(len(args[0])):
            data.append(np.concatenate([d[j] for d in args], axis=0))
    else:
        data = np.concatenate([d for d in args], axis=0)

    return data


class Subset(object):

    def __init__(self, input=None, target=None):
        self.input = input
        self.target = target

    def prepare(self, irange):
        if isinstance(self.input, list):
            for x in self.input:
                x.prepare(irange)
        else:
            self.input.prepare(irange)


# Path: dlearn/data/hidata.py
# class HierarData(object):
# 
#     def __init__(self, data, limit=None):
#         self._cpu_data = data
# 
#         if limit is None or limit > data.shape[0]:
#             limit = data.shape[0]
#         self._limit = limit
# 
#         self._gpu_data = create_shared(self._cpu_data[0:limit])
#         self._cur_irange = create_shared(np.asarray([0, limit]))
# 
#     def prepare(self, irange):
#         l, r = irange
#         cur_l, cur_r = self._cur_irange.get_value(borrow=True)
# 
#         if min(l, r - 1) < cur_l or max(l, r - 1) >= cur_r:
#             self._cur_irange.set_value(np.asarray([l, l + self._limit]))
#             self._gpu_data.set_value(
#                 self._cpu_data[l:l + self._limit], borrow=True)
# 
#     @property
#     def cur_irange(self):
#         return self._cur_irange
# 
#     @property
#     def cpu_data(self):
#         return self._cpu_data
# 
#     @property
#     def gpu_data(self):
#         return self._gpu_data
# 
# Path: dlearn/utils/math.py
# def create_shared(x):
# def create_empty(p):
# def dropout(x, ratio):


# Path: dlearn/data/dataset.py
import numpy as np
from .hidata import HierarData
from ..utils.math import nprng



def _get_n(data):
    return data[0].shape[0] if isinstance(data, list) else data.shape[0]


def _combine(*args):
    if isinstance(args[0], list):
        data = []
        for j in xrange(len(args[0])):
            data.append(np.concatenate([d[j] for d in args], axis=0))
    else:
        data = np.concatenate([d for d in args], axis=0)

    return data


class Subset(object):

    def __init__(self, input=None, target=None):
        self.input = input
        self.target = target

    def prepare(self, irange):
        if isinstance(self.input, list):
            for x in self.input:
                x.prepare(irange)
        else:
            self.input.prepare(irange)


        if isinstance(self.target, list):