www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Forward Difference Compression

I'm working on a range-based generic codec that uses 
forwardDifference (and its reverse not yet implemented) in 
combination with msgpack to pack arrays of 64-bit timestamps for 
compacter storage.

My solution so far looks like can be found here



auto forwardDifference(R)(R r)
     pure nothrow if (isInputRange!R)
     import std.range: front, empty, popFront;

     struct ForwardDifference
         R _range;
         alias E = ElementType!R;                       // Input 
         alias D = typeof(_range.front - _range.front); // Element 
Difference Type
         D _front;
         bool _initialized = false;

         this(R range) pure {
             this._range = range;

         auto ref front() {
             if (!_initialized) { popFront(); }
             return _front;
         auto ref moveFront() {
             return _front;
         void popFront() {
             if (empty is false) {
                 _initialized = true;
                 E rf = _range.front;
                 if (_range.empty is false)
                     _front = _range.front - rf;
         bool empty() { return _range.empty; }

     return ForwardDifference(r);

auto packForwardDifference(R)(R r) if (isInputRange!R)
     import std.range: front, empty;
     if (r.empty)
         return tuple(r.front, forwardDifference(r));
         return tuple(r.front, forwardDifference(r));

unittest {
     import std.range: front;
     dln([1, 22].packForwardDifference);
     dln([1, 22, 333].packForwardDifference);

gives the output

algorithm_ex.d:753:debug: Tuple!(int, ForwardDifference)(1, [0])
algorithm_ex.d:754:debug: Tuple!(int, ForwardDifference)(1, [21])
algorithm_ex.d:755:debug: Tuple!(int, ForwardDifference)(1, [21, 

the corner cases
- input []: throws exception on front and
- input [1]: outputs [0] which is incorrect and should give 
output [].

How can I efficiently treat these special cases without using 
.length property?

I want this to work for InputRanges, not just arrays.
Mar 22 2014