stepcompress: Compress for greatest "reach" instead of greatest "add"

Search for the maximum reachable value instead of the maximum "add".
The maximum reachable value encompasses both the maximum count and a
closest step time to the last requested step time.  This allows for
more "add=0" sequences to be generated which the mcu can optimize for.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-09-22 16:40:00 -04:00
parent 0685802cb8
commit 47f303317b
1 changed files with 23 additions and 21 deletions

View File

@ -140,13 +140,13 @@ compress_bisect_add(struct stepcompress *sc)
if (last > sc->queue_pos + 65535) if (last > sc->queue_pos + 65535)
last = sc->queue_pos + 65535; last = sc->queue_pos + 65535;
struct points point = minmax_point(sc, sc->queue_pos); struct points point = minmax_point(sc, sc->queue_pos);
int32_t origmininterval = point.minp, origmaxinterval = point.maxp; int32_t outer_mininterval = point.minp, outer_maxinterval = point.maxp;
int32_t add = 0, minadd = -0x8001, maxadd = 0x8000; int32_t add = 0, minadd = -0x8001, maxadd = 0x8000;
int32_t bestadd=0, bestcount=0, bestinterval=0; int32_t bestinterval = 0, bestcount = 0, bestadd = 0, bestreach = 0;
for (;;) { for (;;) {
// Find longest valid sequence with the given 'add' // Find longest valid sequence with the given 'add'
int32_t mininterval = origmininterval, maxinterval = origmaxinterval; int32_t mininterval = outer_mininterval, maxinterval = outer_maxinterval;
int32_t count = 1, addfactor = 0; int32_t count = 1, addfactor = 0;
for (;;) { for (;;) {
if (sc->queue_pos + count >= last) if (sc->queue_pos + count >= last)
@ -166,30 +166,26 @@ compress_bisect_add(struct stepcompress *sc)
mininterval = nextmininterval; mininterval = nextmininterval;
maxinterval = nextmaxinterval; maxinterval = nextmaxinterval;
} }
if (count > bestcount || (count == bestcount && add > bestadd)) {
// Check if this is the best sequence found so far
int32_t reach = add*(addfactor-count) + maxinterval*count;
if (reach > bestreach) {
bestinterval = maxinterval;
bestcount = count; bestcount = count;
bestadd = add; bestadd = add;
bestinterval = maxinterval; bestreach = reach;
} }
// Check if a greater or lesser add could extend the sequence // Check if a greater or lesser add could extend the sequence
int32_t maxreach = add*addfactor + maxinterval*(count+1); int32_t nextreach = add*addfactor + maxinterval*(count+1);
if (maxreach < point.minp) { if (nextreach < point.minp) {
minadd = add; minadd = add;
origmaxinterval = maxinterval; outer_maxinterval = maxinterval;
} else { } else {
maxadd = add; maxadd = add;
origmininterval = mininterval; outer_mininterval = mininterval;
} }
// See if next point would further limit the add range
if ((minadd+1)*addfactor + origmaxinterval*(count+1) < point.minp)
minadd = idiv_up(point.minp - origmaxinterval*(count+1)
, addfactor) - 1;
if ((maxadd-1)*addfactor + origmininterval*(count+1) > point.maxp)
maxadd = idiv_down(point.maxp - origmininterval*(count+1)
, addfactor) + 1;
// The maximum valid deviation between two quadratic sequences // The maximum valid deviation between two quadratic sequences
// can be calculated and used to further limit the add range. // can be calculated and used to further limit the add range.
if (count > 1) { if (count > 1) {
@ -200,13 +196,19 @@ compress_bisect_add(struct stepcompress *sc)
maxadd = add + errdelta; maxadd = add + errdelta;
} }
// See if next point would further limit the add range
if ((minadd+1)*addfactor + outer_maxinterval*(count+1) < point.minp)
minadd = idiv_up(point.minp - outer_maxinterval*(count+1)
, addfactor) - 1;
if ((maxadd-1)*addfactor + outer_mininterval*(count+1) > point.maxp)
maxadd = idiv_down(point.maxp - outer_mininterval*(count+1)
, addfactor) + 1;
// Bisect valid add range and try again with new 'add' // Bisect valid add range and try again with new 'add'
add = (maxadd + minadd) / 2; add = (minadd + maxadd) / 2;
if (add <= minadd || add >= maxadd) if (add <= minadd || add >= maxadd)
break; break;
} }
if (bestcount < 2)
bestadd = 0;
return (struct step_move){ bestinterval, bestcount, bestadd }; return (struct step_move){ bestinterval, bestcount, bestadd };
} }