diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
index c027f4128c81484870af11803d7f7229081ae466..4a682da76bec22cb01897d081433dde9a0ebd51a 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
@@ -74,12 +74,12 @@ public class Icp {
             List<Double> distances = hausdorffDist.getDistances().get(transformedFacet);
             List<Point3d> nearestPoints = hausdorffDist.getNearestPoints().get(transformedFacet);
 
-            if(transformation != null){
+            if (transformation != null) {
                 prevMeanD = transformation.getMeanD();
             }
 
             transformation = computeIcpTransformation(nearestPoints, distances);
-            //transformations.add(transformation);
+            transformations.add(transformation);
             applyTransformation(transformation);
             currentIteration ++;
         }
@@ -103,11 +103,11 @@ public class Icp {
 
     /**
      * Compute transformation parameters( translation, rotation and scale factor).
-     * Based on old Fidentis implementation
+     * Based on old FIDENTIS implementation
      *
      * @param nearestPoints List of nearest points computed by Hausdorff distance.
      * @param distances list of distances computed by Hausdorff distance
-     * @return Return Icp transformation which is represented by computed parameters.
+     * @return Return ICP transformation which is represented by computed parameters.
 
      */
     private IcpTransformation computeIcpTransformation(List<Point3d> nearestPoints, List<Double> distances) {
@@ -148,24 +148,8 @@ public class Icp {
 
         // END computing translation parameter
 
-        EigenvalueDecomposition matrix = new EigenvalueDecomposition(sumMatrix);
-        Matrix4d eigD = matrix.getD();
-        Matrix4d eigM = matrix.getV();
-        int max = 0;
-
-        //Finding quaternion q representing the rotation
-        // (it is the eigenvector corresponding to the largest eigenvalue of sumMatrix)
-        for (int i = 0; i < 4; i++) {
-            if (eigD.getElement(max, max) <= eigD.getElement(i, i)) {
-                max = i;
-            }
-        }
-        Quaternion q = new Quaternion(
-                eigM.getElement(0, max), 
-                eigM.getElement(1, max), 
-                eigM.getElement(2, max),
-                eigM.getElement(3, max));
-        q = q.normalize();
+        Quaternion q = new Quaternion(new EigenvalueDecomposition(sumMatrix));
+        q.normalize();
         // END computing rotation parameter
 
         //computing SCALE parameter
@@ -175,27 +159,21 @@ public class Icp {
 
         if (scale) {
             Matrix4d rotationMatrix = q.toMatrix();
-
-            Matrix4d matrixPoint, matrixPointCompare;
-
             for (int i = 0; i < nearestPoints.size(); i++) {
                 if(nearestPoints.get(i) == null) {
                     continue;
                 }
 
-                matrixPoint = pointToMatrix(relativeCoordinate(nearestPoints.get(i), mainCenter));
-                matrixPointCompare = pointToMatrix(relativeCoordinate(comparedPoints.get(i).getPosition(),comparedCenter));
+                Matrix4d matrixPoint = pointToMatrix(relativeCoordinate(nearestPoints.get(i), mainCenter));
+                Matrix4d matrixPointCompare = pointToMatrix(relativeCoordinate(comparedPoints.get(i).getPosition(),comparedCenter));
 
                 matrixPointCompare.mul(rotationMatrix);
 
-                Matrix4d tmp1 = new Matrix4d();
-                Matrix4d tmp2 = new Matrix4d();
+                matrixPoint.mulTransposeLeft(matrixPoint, matrixPointCompare);
+                matrixPointCompare.mulTransposeLeft(matrixPointCompare, matrixPointCompare);
 
-                tmp1.mulTransposeLeft(matrixPoint, matrixPointCompare);
-                tmp2.mulTransposeLeft(matrixPointCompare, matrixPointCompare);
-
-                sxUp += tmp1.getElement(0, 0);
-                sxDown += tmp2.getElement(0,0);
+                sxUp += matrixPoint.getElement(0, 0);
+                sxDown += matrixPointCompare.getElement(0,0);
             }
 
             scaleFactor = sxUp / sxDown;
@@ -212,30 +190,25 @@ public class Icp {
      */
     private void applyTransformation(IcpTransformation transformation) {
         Point3d meshPointPosition;
-        Quaternion rotationCopy;
-
-        Quaternion rotation;
         for (MeshPoint comparedPoint : transformedFacet.getVertices()) {
             meshPointPosition = comparedPoint.getPosition();
-            Quaternion point = new Quaternion(1, meshPointPosition.x, meshPointPosition.y, meshPointPosition.z);
-
+            Quaternion rotation = new Quaternion(meshPointPosition.x, meshPointPosition.y, meshPointPosition.z, 1);
+            
             if (transformedFacet.getVertices().size() > 1) {
-                rotationCopy = Quaternion.multiply(point, transformation.getRotation().getConjugate());
+                Quaternion rotationCopy = Quaternion.multiply(rotation, transformation.getRotation().getConjugate());
                 rotation = Quaternion.multiply(transformation.getRotation(), rotationCopy);
-            } else {
-                rotation = point;
             }
 
             if(scale && !Double.isNaN(transformation.getScaleFactor())) {
                 meshPointPosition.set(
-                        rotation.getX() * transformation.getScaleFactor() + transformation.getTranslation().x,
-                        rotation.getY() * transformation.getScaleFactor() + transformation.getTranslation().y,
-                        rotation.getZ() * transformation.getScaleFactor() + transformation.getTranslation().z);
+                        rotation.x * transformation.getScaleFactor() + transformation.getTranslation().x,
+                        rotation.y * transformation.getScaleFactor() + transformation.getTranslation().y,
+                        rotation.z * transformation.getScaleFactor() + transformation.getTranslation().z);
             } else {
                 meshPointPosition.set(
-                        rotation.getX() + transformation.getTranslation().x,
-                        rotation.getY() + transformation.getTranslation().y ,
-                        rotation.getZ() + transformation.getTranslation().z);
+                        rotation.x + transformation.getTranslation().x,
+                        rotation.y + transformation.getTranslation().y ,
+                        rotation.z + transformation.getTranslation().z);
             }
         }
     }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java
index c8d8c24dc163993e6d7f099e0812067e6cd64f27..11aede9cb40b154c48e0fb000d0b50c75edc88a1 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/Quaternion.java
@@ -1,18 +1,18 @@
 package cz.fidentis.analyst.icp;
 
 import javax.vecmath.Matrix4d;
+import javax.vecmath.Quat4d;
+import javax.vecmath.Vector3d;
 
 /**
- * This class represents quaternions.
+ * This class represents quaternions. 
+ * Primary, it fixes the error in the {@code Quat4d} constructor, which normalizes
+ * the given coordinates for some reason. Moreover, this extension
+ * introduces useful methods that accelerate the ICP calculation a bit.
  *
  * @author Maria Kocurekova
  */
-public final class Quaternion {
-    
-    private final double w;
-    private final double x;
-    private final double y;
-    private final double z;
+public final class Quaternion extends Quat4d {
     
     /**
      * Builds a quaternion from its components.
@@ -22,102 +22,70 @@ public final class Quaternion {
      * @param y Second vector component.
      * @param z Third vector component.
      */
-    public Quaternion(double w, double x, double y, double z) {
-        this.w = w;
+    public Quaternion(double x, double y, double z, double w) {
         this.x = x;
         this.y = y;
         this.z = z;
+        this.w = w;
     }
-
-    /**
-     * Gets the second component of the quaternion (first component
-     * of the vector part).
-     *
-     * @return the first component of the vector part.
-     */
-    public double getX(){
-        return x;
-    }
-
-    /**
-     * Gets the third component of the quaternion (second component
-     * of the vector part).
-     *
-     * @return the second component of the vector part.
-     */
-    public double getY(){
-        return y;
-    }
-
+    
     /**
-     * Gets the fourth component of the quaternion (third component
-     * of the vector part).
-     *
-     * @return the third component of the vector part.
+     * Builds a quaternion from eigenvalue decomposition.
+     * 
+     * @param ev eigenvalue decomposition.
      */
-    public double getZ(){
-        return z;
-    }
+    public Quaternion(EigenvalueDecomposition ev) {
+        Matrix4d eigD = ev.getD();
+        Matrix4d eigM = ev.getV();
+        int max = 0;
 
-    /**
-     * Gets the first component of the quaternion (scalar part).
-     *
-     * @return the scalar part.
-     */
-    public double getW(){
-        return w;
+        //Finding quaternion q representing the rotation
+        // (it is the eigenvector corresponding to the largest eigenvalue of sumMatrix)
+        for (int i = 0; i < 4; i++) {
+            if (eigD.getElement(max, max) <= eigD.getElement(i, i)) {
+                max = i;
+            }
+        }
+        
+        this.x = eigM.getElement(1, max);
+        this.y = eigM.getElement(2, max);
+        this.z = eigM.getElement(3, max);
+        this.w = eigM.getElement(0, max);
     }
 
     /**
      * Returns the conjugate quaternion of the instance.
+     * It method is equivalent to calling the {@link #conjugate} method, 
+     * but it is more effective and readable when the origin quaternion has to be preserved.
      *
      * @return the conjugate quaternion
      */
     public Quaternion getConjugate() {
-        return new Quaternion(w, -x, -y, -z);
+        return new Quaternion(-x, -y, -z, w);
     }
 
     /**
      * Returns the Hamilton product of two quaternions.
+     * It is equivalent to {@code q1.mul(q2)} of {@code Quat4d}.
+     * But calling this method it is faster and more readable if the first quaternion 
+     * has to be preserved (and then cloned first).
      *
      * @param q1 First quaternion.
      * @param q2 Second quaternion.
      * @return the Hamilton product of two quaternions
      */
     public static Quaternion multiply(final Quaternion q1, final Quaternion q2) {
-        // Components of the first quaternion.
-        final double q1w = q1.getW();
-        final double q1x = q1.getX();
-        final double q1y = q1.getY();
-        final double q1z = q1.getZ();
-
-        // Components of the second quaternion.
-        final double q2w = q2.getW();
-        final double q2x = q2.getX();
-        final double q2y = q2.getY();
-        final double q2z = q2.getZ();
-
-        // Components of the product.
-        final double w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
-        final double x = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;
-        final double y = q1w * q2y - q1x * q2z + q1y * q2w + q1z * q2x;
-        final double z = q1w * q2z + q1x * q2y - q1y * q2x + q1z * q2w;
-
-        return new Quaternion(w, x, y, z);
-    }
-
-    /**
-     * Computes the normalized quaternion
-     *
-     * @return a normalized quaternion
-     */
-    public Quaternion normalize() {
-        double norm = Math.sqrt(w * w + x * x + y * y + z * z);
-        return new Quaternion(w / norm, x / norm, y / norm, z / norm);
+        final double w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
+        final double x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
+        final double y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
+        final double z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
+        return new Quaternion(x, y, z, w);
     }
 
     /**
-     * Convert a Quaternion to a rotation matrix
+     * Convert a Quaternion to a rotation matrix. 
+     * It is equivalent to but bit faster than calling 
+     * {@code new Matrix4d(quternion, new Vector3d(0,0,0), 1);}
      *
      * @return a rotation matrix (4x4)
      */
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
index 59a693005f81601459f3cdf22b41b52a873edc64..09fce379447f18a48d9fe0b5e9a930576a63b3fc 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
@@ -40,17 +40,14 @@ public class EfficiencyTests {
      */
     public static void main(String[] args) throws IOException, ClassNotFoundException, Exception {
         face1 = printFaceLoad(faceFile4);
-        face2 = printFaceLoad(faceFile4);
+        face2 = printFaceLoad(faceFile2);
         
         face1.getMeshModel().simplifyModel();
         face2.getMeshModel().simplifyModel();
         
-        for (int i = 0; i < 10; i++) {
-            //HumanFace face = HumanFacePrivilegedCache.instance().loadFace(faceFile4);
-            //face.getMeshModel().simplifyModel();
-            //System.out.println(i+".\t" + HumanFacePrivilegedCache.instance());
-            printFaceDump(face1);
-        }
+        //for (int i = 0; i < 10; i++) {
+        //    printFaceDump(face1);
+        //}
         
         boolean relativeDist = false;
         boolean printDetails = false;
@@ -58,9 +55,9 @@ public class EfficiencyTests {
         
         //face1.getMeshModel().compute(new GaussianCurvature()); // initialize everything, then measure
         
-        System.out.println("ICP:");
-        Icp icp = new Icp();
-        icp.getTransformedFacet(face1.getMeshModel().getFacets().get(0), face2.getMeshModel().getFacets().get(0));
+        System.out.println();
+        System.out.println("ICP calculation:");
+        printIcp(face1, face2);
         
         System.out.println("Symmetry plane calculation:");
         printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.MEAN);
@@ -149,6 +146,15 @@ public class EfficiencyTests {
         return face;
     }
     
+    private static void printIcp(HumanFace face1, HumanFace face2) throws IOException {
+        long startTime = System.currentTimeMillis();
+        Icp icp = new Icp();
+        icp.setParameters(100, false, 0.001);
+        icp.getTransformedFacet(face1.getMeshModel().getFacets().get(0), face2.getMeshModel().getFacets().get(0));
+        long endTime =  System.currentTimeMillis();
+        System.out.println("ICP:\t " +(endTime-startTime) + " msec, " + (icp.getTransformations().size()+1) + " iterations");
+    }
+    
     public static String formatSize(long v) {
         if (v < 1024) return v + " B";
         int z = (63 - Long.numberOfLeadingZeros(v)) / 10;