         return base.elementShape?.prepending(count) ?? .scalar
     }
 
-    public var items: ArraySlice<Base.ItemType> {
-        return base.items[base.itemSubrange(from: baseRange)]
-    }
-
-    var itemCount: Int {
-        return count * base.itemCountPerElement
-    }
-
-}
-
-// MARK: - Reshaping
+    public var units: ArraySlice<Base.UnitType> {
+        return base.units[base.unitSubrange(from: baseRange)]
+    }
+
+    var unitCount: Int {
+        return count * base.unitCountPerElement
+    }
+
+}
+
 public extension Tensor {
 
     public func reshaped(as newShape: TensorShape) -> Tensor? {
         guard self.shape.contiguousSize == newShape.contiguousSize else {
             return nil
         }
-        return Tensor(shape: newShape, items: items)
-    }
-
-}
-
-// MARK: - Unsafe access
+        return Tensor(shape: newShape, units: units)
+    }
+
+}
+
 public extension Tensor {
 
     func withUnsafeBufferPointer<Result>
-        (_ body: (UnsafeBufferPointer<ItemType>) throws -> Result) rethrows -> Result {
-        return try items.withUnsafeBufferPointer { ptr in
+        (_ body: (UnsafeBufferPointer<UnitType>) throws -> Result) rethrows -> Result {
+        return try units.withUnsafeBufferPointer { ptr in
             try body(ptr)
         }
     }
 
     mutating func withUnsafeMutableBufferPointer<Result>
-        (_ body: (inout UnsafeMutableBufferPointer<ItemType>) throws -> Result) rethrows -> Result {
-        return try items.withUnsafeMutableBufferPointer { ptr in
+        (_ body: (inout UnsafeMutableBufferPointer<UnitType>) throws -> Result) rethrows -> Result {
+        return try units.withUnsafeMutableBufferPointer { ptr in
             try body(&ptr)
         }
     }
 
 }
 
-// MARK: - Textual description
 extension Tensor : TextOutputStreamable {
     public func write<Target>(to target: inout Target) where Target : TextOutputStream {
         target.write(
-            isScalar ? String(describing: items[0])
+            isScalar ? String(describing: units[0])
                      : "[\(map{"\($0)"}.joined(separator: ", "))]"
         )
     }

        return elementShape?.prepending(count) ?? .scalar
    }

    var itemCount: Int {
        return items.count
    }

    func item(at index: Int) -> ItemType {
        return items[items.startIndex.advanced(by: index)]
    }

    func item(at index: TensorIndex) -> ItemType {
        return self[index].items[0]
    }
}

internal extension TensorProtocol where IndexDistance == Int {
    func itemIndex(fromIndex index: Int) -> Int {
        return itemCountPerElement * index
    }

    func itemSubrange(from tensorSubrange: Range<Int>) -> Range<Int> {
        return itemIndex(fromIndex: tensorSubrange.lowerBound)
           ..< itemIndex(fromIndex: tensorSubrange.upperBound)
    }
}

/// Tensor
public struct Tensor<ItemType> : TensorProtocol {
    public typealias Element = Tensor<ItemType>

    /// Sub-tensor (element) shape
    public internal(set) var elementShape: TensorShape? {
        didSet {
            itemCountPerElement = elementShape?.contiguousSize ?? 0
        }
    }



}

extension Tensor where UnitType : Strideable {

    public init(shape: TensorShape, unitsIncreasingFrom lowerBound: UnitType) {
        var unit = lowerBound
        self.init(shape: shape, supplier: {
            defer { unit = unit.advanced(by: 1) }
            return unit
        })
    }

}

extension Tensor where UnitType : Strideable, UnitType.Stride : SignedInteger {

    public init(scalarElementsIn bounds: CountableRange<UnitType>) {
        self.init(elementShape: .scalar, units: ContiguousArray(bounds))
    }

    public init(scalarElementsIn bounds: CountableClosedRange<UnitType>) {
        self.init(elementShape: .scalar, units: ContiguousArray(bounds))
    }

}

public extension Tensor {

    func makeUnitIterator() -> IndexingIterator<ContiguousArray<UnitType>> {
        return units.makeIterator()
    }

    mutating func updateUnit(at index: Int, to newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] = newValue
    }

}

public extension Tensor where UnitType : Numeric {

    mutating func incrementUnit(at index: Int, by newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] += newValue
    }

    mutating func decrementUnit(at index: Int, by newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] -= newValue
    }

    mutating func multiplyUnit(at index: Int, by newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] *= newValue
    }

}

public extension Tensor where UnitType : BinaryInteger {
    mutating func divideUnit(at index: Int, by newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] /= newValue
    }
}

public extension Tensor where UnitType : FloatingPoint {
    mutating func divideUnit(at index: Int, by newValue: UnitType) {
        units[units.startIndex.advanced(by: index)] /= newValue
    }
}

internal extension RangeReplaceableRandomAccessSlice {
