Clean up duplicated depth interpolation

Linus Torvalds torvalds at linux-foundation.org
Tue Jan 8 15:48:23 PST 2013


We have several places where we interpolate the depth based on two 
samples and the time between them. Some of them use floating point, some 
of them don't, some of them meant to do it but didn't.

Just use a common helper function for it. I seriously doubt the floating 
point here really matters, since doing it in integers is not going to 
overflow unless we're interpolating between two samples that are hours 
apart at hundreds of meters of depth, but hey, it gives that rounding to 
the nearest millimeter. Which I'm sure matters.

Anyway, we can probably just get rid of the rounding and the floating 
point math, but it won't really hurt either, so at least do it 
consistently.

The interpolation could be for other things than just depth, but we 
probably don't have anything else we'd want to interpolate. But make the 
function naming generic just in case.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
 dive.h     |  9 +++++++++
 divelist.c |  3 +--
 planner.c  |  2 +-
 profile.c  | 14 ++------------
 4 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/dive.h b/dive.h
index ec03bf56275f..bf2a4b841fb4 100644
--- a/dive.h
+++ b/dive.h
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <time.h>
+#include <math.h>
 
 #include <glib.h>
 #include <glib/gstdio.h>
@@ -221,6 +222,14 @@ static inline int mbar_to_PSI(int mbar)
 	return to_PSI(p);
 }
 
+/* Linear interpolation between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
+static inline int interpolate(int a, int b, int part, int whole)
+{
+	/* It is doubtful that we actually need floating point for this, but whatever */
+	double x = (double) a * (whole - part) + (double) b * part;
+	return rint(x / whole);
+}
+
 struct sample {
 	duration_t time;
 	depth_t depth;
diff --git a/divelist.c b/divelist.c
index aaf7d2fcba12..024d9bfb373f 100644
--- a/divelist.c
+++ b/divelist.c
@@ -834,8 +834,7 @@ static void add_dive_to_deco(struct dive *dive)
 		int j;
 
 		for (j = t0; j < t1; j++) {
-			int depth = 0.5 + psample->depth.mm + (j - t0) *
-					(sample->depth.mm - psample->depth.mm) / (t1 - t0);
+			int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
 			(void) add_segment(depth_to_mbar(depth, dive) / 1000.0,
 					   &dive->cylinder[sample->sensor].gasmix, 1, sample->po2 / 1000.0, dive);
 		}
diff --git a/planner.c b/planner.c
index 9d304af2b818..53978fe0f015 100644
--- a/planner.c
+++ b/planner.c
@@ -69,7 +69,7 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
 		if (i > 0)
 			lastdepth = psample->depth.mm;
 		for (j = t0; j < t1; j++) {
-			int depth = lastdepth + (j - t0) * (sample->depth.mm - lastdepth) / (t1 - t0);
+			int depth = interpolate(lastdepth, sample->depth.mm, j - t0, t1 - t0);
 			tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0,
 						       &dive->cylinder[sample->sensor].gasmix, 1, sample->po2, dive);
 		}
diff --git a/profile.c b/profile.c
index b77541286520..4b71ce8d050f 100644
--- a/profile.c
+++ b/profile.c
@@ -8,7 +8,6 @@
 #include <stdarg.h>
 #include <string.h>
 #include <time.h>
-#include <math.h>
 
 #include "dive.h"
 #include "display.h"
@@ -1596,15 +1595,6 @@ static void calculate_max_limits(struct dive *dive, struct divecomputer *dc, str
 	pi->maxtemp = maxtemp;
 }
 
-/* Average between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
-static int average_depth(int a, int b, int part, int whole)
-{
-	double x;
-
-	x = (a * (whole - part) + b * part) / whole;
-	return rint(x);
-}
-
 static struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
 {
 	int idx, maxtime, nr, i;
@@ -1653,7 +1643,7 @@ static struct plot_data *populate_plot_entries(struct dive *dive, struct divecom
 
 			/* .. but update depth and time, obviously */
 			entry->sec = lasttime + offset;
-			entry->depth = average_depth(lastdepth, depth, offset, delta);
+			entry->depth = interpolate(lastdepth, depth, offset, delta);
 
 			/* And clear out the sensor pressure, since we'll interpolate */
 			SENSOR_PRESSURE(entry) = 0;
@@ -1867,7 +1857,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
 		t1 = entry->sec;
 		tissue_tolerance = 0;
 		for (j = t0; j < t1; j++) {
-			int depth = 0.5 + (entry - 1)->depth + (j - t0) * (entry->depth - (entry - 1)->depth) / (t1 - t0);
+			int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
 			double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0,
 							&dive->cylinder[cylinderindex].gasmix, 1, entry->po2, dive);
 			if (min_pressure > tissue_tolerance)


More information about the subsurface mailing list