diff --git a/bob/measure/cpp/error.cpp b/bob/measure/cpp/error.cpp
index a67f28ffd0cdbb3978632928694d1933c9fd0af0..facf8114b9c5b989991f6956d0ec639bbb86b14d 100644
--- a/bob/measure/cpp/error.cpp
+++ b/bob/measure/cpp/error.cpp
@@ -421,73 +421,21 @@ bob::measure::roc_for_far(const blitz::Array<double, 1> &negatives,
   sort(negatives, neg, is_sorted);
   sort(positives, pos, is_sorted);
 
-  // do some magic to compute the FRR list
   blitz::Array<double, 2> retval(2, n_points);
 
-  // index into the FAR and FRR list
+  // index into the FAR list
   int far_index = n_points - 1;
-  int pos_index = 0, neg_index = 0;
-  int n_pos = pos.extent(0), n_neg = neg.extent(0);
-
-  // iterators into the result lists
-  auto pos_it = pos.begin(), neg_it = neg.begin();
-  // do some fast magic to compute the FRR values ;-)
-  do {
-    // check whether the current positive value is less than the current
-    // negative one
-    if (*pos_it < *neg_it) {
-      // increase the positive count
-      ++pos_index;
-      // go to the next positive value
-      ++pos_it;
-    } else {
-      // increase the negative count
-      ++neg_index;
-      // go to the next negative value
-      ++neg_it;
-    }
-    // check, if we have reached a new FAR limit,
-    // i.e. if the relative number of negative similarities is greater than
-    // 1-FAR (which is the CRR)
-
-    if (((double)neg_index / (double)n_neg > 1. - far_list(far_index)) &&
-        !(bob::core::isClose((double)neg_index / (double)n_neg,
-                             1. - far_list(far_index), 1e-9, 1e-9))) {
-      // copy the far value
-      retval(0, far_index) = far_list(far_index);
-      // calculate the FRR for the current FAR
-      retval(1, far_index) = (double)pos_index / (double)n_pos;
-      // go to the next FAR value
-      --far_index;
-    }
 
-    // do this, as long as there are elements in both lists left and not all FRR
-    // elements where calculated yet
-  } while (pos_it != pos.end() && neg_it != neg.end() && far_index >= 0);
-
-  // check if all FRR values have been set
-  if (far_index >= 0) {
-    // walk to the end of both lists; at least one of both lists should already
-    // have reached its limit.
-    while (pos_it != pos.end() && pos_it++ != pos.end())
-      ++pos_index;
-    while (neg_it != neg.end() && neg_it++ != neg.end())
-      ++neg_index;
-    // fill in the remaining elements of the CAR list
-    do {
-      // copy the FAR value
-      retval(0, far_index) = far_list(far_index);
-      // check if the criterion is fulfilled (should be, as long as the lowest
-      // far is not below 0)
-      if ((double)neg_index / (double)n_neg > 1. - far_list(far_index)) {
-        // calculate the FRR for the current FAR
-        retval(1, far_index) = (double)pos_index / (double)n_pos;
-      } else {
-        // set FRR to 1 (this should never happen, but might be due to numerical
-        // issues)
-        retval(1, far_index) = 1.;
-      }
-    } while (far_index--);
+  // Get the threshold for the requested far values and calculate far and frr
+  // values based on the threshold.
+  while(far_index >= 0) {
+    // calculate the threshold for the requested far
+    auto threshold = bob::measure::farThreshold(neg, pos, far_list(far_index), true);
+    // calculate the frr and re-calculate the far
+    auto farfrr = bob::measure::farfrr(neg, pos, threshold);
+    retval(0, far_index) = farfrr.first;
+    retval(1, far_index) = farfrr.second;
+    far_index--;
   }
 
   return retval;
diff --git a/bob/measure/data/nonsep-det.hdf5 b/bob/measure/data/nonsep-det.hdf5
index 82e94bdc0f1536556552ccb84e95c97d09a58eb8..27c703b4247754a4b26270cfb1b1d97dc8e7ca9d 100644
Binary files a/bob/measure/data/nonsep-det.hdf5 and b/bob/measure/data/nonsep-det.hdf5 differ
diff --git a/bob/measure/data/nonsep-roc.hdf5 b/bob/measure/data/nonsep-roc.hdf5
index ab2c517098768664fe03bf33b4ed63879d92ec44..4b00e0d61cea8c40ec5cd89ee2e2394c0a578683 100644
Binary files a/bob/measure/data/nonsep-roc.hdf5 and b/bob/measure/data/nonsep-roc.hdf5 differ
diff --git a/bob/measure/main.cpp b/bob/measure/main.cpp
index eb68dbc8e4f42d617ab739ed879cc8d13adc1efa..1afcb9c64ed8d4423dc11a84ba33cc3883139040 100644
--- a/bob/measure/main.cpp
+++ b/bob/measure/main.cpp
@@ -714,11 +714,7 @@ static auto far_threshold_doc =
     bob::extension::FunctionDoc(
         "far_threshold", "Computes the threshold such that the real FAR is "
                          "**at most** the requested ``far_value`` if possible",
-        "If no such threshold can be computed, ``NaN`` is returned. It is "
-        "impossible to compute the threshold, when too few non-identical "
-        "highest scores exist, so that the desired ``far_value`` cannot be "
-        "reached by any threshold.\n\n"
-        ".. note::\n\n"
+        "\n\n.. note::\n\n"
         "   The scores will be sorted internally, requiring the scores to be "
         "copied.\n"
         "   To avoid this copy, you can sort the ``negatives`` scores "
@@ -774,11 +770,7 @@ static auto frr_threshold_doc =
     bob::extension::FunctionDoc(
         "frr_threshold", "Computes the threshold such that the real FRR is "
                          "**at most** the requested ``frr_value`` if possible",
-        "If no such threshold can be computed, ``NaN`` is returned. It is "
-        "impossible to compute the threshold, when too few non-identical "
-        "lowest scores exist, so that the desired ``frr_value`` cannot be "
-        "reached by any threshold.\n\n"
-        ".. note::\n\n"
+        "\n\n.. note::\n\n"
         "   The scores will be sorted internally, requiring the scores to be "
         "copied.\n"
         "   To avoid this copy, you can sort the ``positives`` scores "
diff --git a/bob/measure/test_error.py b/bob/measure/test_error.py
index f7e727a7f79d136dac91c306b1777094318e35c0..e0d6064868613a64aca7df318768c4e6c7ae9f88 100644
--- a/bob/measure/test_error.py
+++ b/bob/measure/test_error.py
@@ -293,17 +293,18 @@ def test_plots():
   assert numpy.array_equal(xy, xyref)
 
   # This example will test the ROC for FAR plot calculation functionality.
-  far = [0.01, 0.1, 1]
-  ref = [0.42, 0.12, 0]
-  xy = roc_for_far(negatives, positives, far)
+  requested_far = [0.01, 0.1, 1]
+  expected_far = [0.0, 0.1, 1]
+  expected_frr = [0.48, 0.12, 0]
+  xy = roc_for_far(negatives, positives, requested_far)
 
-  assert numpy.array_equal(xy[0], far)
-  assert numpy.array_equal(xy[1], ref)
+  assert numpy.array_equal(xy[0], expected_far), xy[0]
+  assert numpy.array_equal(xy[1], expected_frr), xy[1]
 
   # This example will test the Precision-Recall plot calculation functionality.
   xy = precision_recall_curve(negatives, positives, 100)
   # uncomment the next line to save a reference value
-  # save('nonsep-roc.hdf5', xy)
+  # save('nonsep-precisionrecall.hdf5', xy)
   xyref = bob.io.base.load(F('nonsep-precisionrecall.hdf5'))
   assert numpy.array_equal(xy, xyref)