diff --git a/bed-and-breakfast.cabal b/bed-and-breakfast.cabal
--- a/bed-and-breakfast.cabal
+++ b/bed-and-breakfast.cabal
@@ -1,5 +1,5 @@
 Name:           bed-and-breakfast
-Version:        0.2.1
+Version:        0.2.2
 Synopsis:       Efficient Matrix operations in 100% Haskell.
 Description:    Efficient Matrix operations in 100% Haskell.
                 .
@@ -32,6 +32,10 @@
                 .
                 [@v0.2.1@] Added @cofactors@, @adjugate@, @minor@, and
                     @minorMatrix@.
+                .
+                [@v0.2.2@] @rank@ works now for any Matrix component
+                    type.
+
 
 License:        MIT
 License-File:   LICENSE
diff --git a/src/Numeric/Matrix.hs b/src/Numeric/Matrix.hs
--- a/src/Numeric/Matrix.hs
+++ b/src/Numeric/Matrix.hs
@@ -77,6 +77,7 @@
 import Prelude hiding (any, all, read, map)
 import qualified Prelude as P
 
+
 data family Matrix e
 
 data instance Matrix Int
@@ -589,22 +590,43 @@
     let m = snd $ bounds mat
         n = snd $ bounds (mat ! 1)
 
+        swap a i j = do
+            tmp <- readArray a i
+            readArray a j >>= writeArray a i
+            writeArray a j tmp
+
     a <- thaws mat >>= arrays
 
-    trace <- flip mapM [1..m] $ \k -> do
-        flip mapM_ [(k+1)..m] $ \i -> do
-            a_i <- readArray a i
-            a_k <- readArray a k
-            flip mapM_ [(k+1)..n] $ \j -> do
-                a_ij <- readArray a_i j
-                a_kj <- readArray a_k j
-                a_ik <- readArray a_i k
-                a_kk <- readArray a_k k
-                writeArray a_i j (a_ij - a_kj * (a_ik `divide` a_kk))
-            writeArray a_i k 0
-        read a k k
+    ixPivot <- newSTRef 1
+    prevR   <- newSTRef 1
 
-    return $ fromIntegral $ length $ filter (/= 0) trace
+    flip mapM_ [1..n] $ \k -> do
+        pivotRow <- readSTRef ixPivot
+
+        switchRow <- mapM (\i -> read a i k) [pivotRow .. m]
+            >>= return . L.findIndex (/= 0)
+
+        when (isJust switchRow) $ do
+            let ix = fromJust switchRow + pivotRow
+            when (pivotRow /= ix) (swap a pivotRow ix)
+
+            a_p   <- readArray a k
+            pivot <- readArray a_p k
+            prev  <- readSTRef prevR
+            
+            flip mapM_ [pivotRow+1..m] $ \i -> do
+                a_i <- readArray a i
+                flip mapM_ [k+1..n] $ \j -> do
+                    a_ij <- readArray a_i j
+                    a_ik <- readArray a_i k
+                    a_pj <- readArray a_p j
+                    writeArray a_i j ((pivot * a_ij - a_ik * a_pj)
+                                        `divide` prev)
+
+            writeSTRef ixPivot (pivotRow + 1)
+            writeSTRef prevR pivot
+
+    readSTRef ixPivot >>= return . (+ negate 1) . fromIntegral
 
 
 _det :: (IArray a e, MArray (u s) e (ST s),
