     public func multiplyRow(at i0: Int, by r: R) {
         switchAlignment(.Rows)
         
-        if rowTable[i0] == nil {
+        guard var row = table[i0] else {
             return
         }
         
-        let n = rowTable[i0]!.count
-        var p = UnsafeMutablePointer(&rowTable![i0]!)
+        let n = row.count
+        var p = UnsafeMutablePointer(&row)
         
         for _ in 0 ..< n {
             let (j, a) = p.pointee
             p.pointee = (j, r * a)
             p += 1
         }
-    }
-    
-    public func multiplyCol(at j0: Int, by r: R) {
-        switchAlignment(.Cols)
-        
-        if colTable[j0] == nil {
-            return
-        }
-        
-        let n = colTable[j0]!.count
-        var p = UnsafeMutablePointer(&colTable![j0]!)
-        
-        for _ in 0 ..< n {
-            let (i, a) = p.pointee
-            p.pointee = (i, r * a)
-            p += 1
+        
+        row = row.filter{ $0.1 != R.zero }
+        
+        if row.count == 0 {
+            table.removeValue(forKey: i0)
+        } else {
+            table[i0] = row
         }
     }
     
     public func addRow(at i0: Int, to i1: Int, multipliedBy r: R = R.identity) {
         switchAlignment(.Rows)
         
-        guard let r0 = rowTable[i0] else {
+        guard let r0 = table[i0] else {
             return
         }
         
-        guard let r1 = rowTable[i1] else {
-            rowTable[i1] = r0.map{ ($0.col, r * $0.value )}
+        guard let r1 = table[i1] else {
+            table[i1] = r0.map{ ($0.0, r * $0.1 )}
             return
         }
         
-        var result: [(col: Int, value: R)] = []
+        var result: [(Int, R)] = []
         
         var (p0, p1) = (UnsafePointer(r0), UnsafePointer(r1))
         var (k0, k1) = (0, 0) // counters

        a.switchAlignment(.Rows)
        b.switchAlignment(.Rows)
        
        for (i, list) in a.rowTable {
            var row: [Int: R] = [:]
            
            for (j, a) in list {
                if let bRow = b.rowTable[j] {
                    for (k, b) in bRow {
                        row[k] = row[k, default: R.zero] + a * b
                    }

            }
        }
        
        if result.count == 0 {
            table.removeValue(forKey: i1)
        } else {
            table[i1] = result
        }
    }
    
    public func swapRows(_ i0: Int, _ i1: Int) {
        switchAlignment(.Rows)
        
        let r0 = table[i0]
        table[i0] = table[i1]
        table[i1] = r0
    }
    
    public func multiplyCol(at j0: Int, by r: R) {
        transpose()
        multiplyRow(at: j0, by: r)
        transpose()
    }
    
    public func addCol(at j0: Int, to j1: Int, multipliedBy r: R = R.identity) {
        transpose()
        addRow(at: j0, to: j1, multipliedBy: r)
        transpose()
    }
    
    public func swapCols(_ j0: Int, _ j1: Int) {
        transpose()
        swapRows(j0, j1)
        transpose()
    }
    
    public func enumerate(row i0: Int, fromCol j0: Int = 0) -> AnySequence<(Int, R)> {
        switch align {
        case .Rows:
            if let row = table[i0] {
                return AnySequence(row.lazy.filter{ (col, _) in col >= j0})
            } else {
                return AnySequence([])
            }
        case .Cols:
            return AnySequence((j0 ..< cols).lazy.flatMap{ j -> (Int, R)? in
                guard let col = self.table[j] else {
                    return nil
                }
                for (i, a) in col {
                    if i == i0 {
                        return (j, a)
                    } else if i > i0 {
                        return nil
                    }
                }
                return nil
            })
        }
    }
    
    public func enumerate(col j0: Int, fromRow i0: Int = 0) -> AnySequence<(Int, R)> {
        transpose()
        let result = enumerate(row: j0, fromCol: i0)
        transpose()
        return result
    }
    
    public static func identity(_ n: Int, align: ComputationalMatrixAlignment = .Rows) -> ComputationalMatrix<R> {
        let components = (0 ..< n).map{ i in MatrixComponent(i, i, R.identity)}
        return ComputationalMatrix(rows: n, cols: n, components: components, align: align)
    }
    
    public static func ==(a: ComputationalMatrix<R>, b: ComputationalMatrix<R>) -> Bool {
        if (a.rows, a.cols) != (b.rows, b.cols) {
            return false
        }
        
        if a.align != b.align {
            b.switchAlignment(a.align)
        }
        
        // wish we could just write `a.table == b.table` ..
        
        return (a.table.keys == b.table.keys) && a.table.keys.forAll{ i in
            let (x, y) = (a.table[i]!, b.table[i]!)
            if x.count != y.count {
                return false
            }
            return (0 ..< x.count).forAll { i in x[i] == y[i] }
        }
    }
    
    public func generateGrid() -> [R] {
        var grid = Array(repeating: R.zero, count: rows * cols)
        switch align {
        case .Rows:
            for (i, list) in table {
                for (j, a) in list {
                    grid[i * cols + j] = a
                }
            }
        case .Cols:
            for (j, list) in table {
                for (i, a) in list {
                    grid[i * cols + j] = a
                }
            }
        }
        return grid
    }
    
    public var description: String {
        return "CMatrix(\(align), \(align == .Rows ? table.sum{ $0.1.count } : table.sum{ $0.1.count } ))"
    }
    
    public var detailDescription: String {
        return description + " [ " + table.flatMap { (i, list) in
            list.map{ (j, a) in "\( align == .Rows ? (i, j, a) : (j, i, a) )"}
            }.joined(separator: ", ") + " ]"
    }
}
