An Alternative Bresenham Counter Implementation

This alternative implementation is slightly slower due to the presence of an extra subtraction.  It is based on what is described here.  This version can produce a different integer sequence to the previous version due to the different decision variable scheme (values are effectively rounded differently); it still produces an evenly distributed scaled range however.

template <typename T>
class bresenham_counter_alt
{
    /* operator T() returns x[0..N-1] = 0 .. R, i.e. x[n] = (R / (N-1)) * n, without
    using floating point or multiplication/division each iteration */
public:
    bresenham_counter_alt(T range, T number) :
        n(number-1),
        partInt(n > 0 ? range / n : 0),
        partFract(n > 0 ? range % n : 0),
        e(0),
        incrCounter(partInt),
        incrCounterPlus1(n > 0 ? incrCounter+1 : 0),
        counter(0) {}
    bresenham_counter_alt(T rangeStart, T rangeEnd, T number) :
        n(number-1),
        partInt(n > 0 ? rangeEnd > rangeStart ?
            (rangeEnd - rangeStart) / n : (rangeStart - rangeEnd) / n : 0),
        partFract(n > 0 ? rangeEnd > rangeStart ?
            (rangeEnd - rangeStart) % n : (rangeStart - rangeEnd) % n: 0),
        e(0),
        incrCounter(rangeEnd > rangeStart ? partInt : -partInt),
        incrCounterPlus1(n > 0 ? rangeEnd > rangeStart ? incrCounter+1 : incrCounter-1 : 0),
        counter(rangeStart) {}
    operator T()
    {
        e += partFract;
        if (e < n)
        {
            T v = counter;
            counter += incrCounter;
            return v;
        }
        else
        {
            e -= n;
            T v = counter;
            counter += incrCounterPlus1;
            return v;
        }
    }
private:
    T n, partInt, partFract, e;
    T incrCounter;
    T incrCounterPlus1;
    T counter;
};

The following test program illustrates the differences between the two versions:

int main()
{
    int a=1, b=123, n=75;
    bresenham_counter<int> bc1(a, b, n);
    bresenham_counter_alt<int> bc2(a, b, n);
    for (int i = 0; i<n; ++i)
        std::cout << i << ": " << bc1 << " " << bc2 << " " << (double)(b-a)*i/(n-1)+a<< std::endl;
    return 0;
}

The output of which is:

0: 1 1 1
1: 3 2 2.64865
2: 4 4 4.2973
3: 6 5 5.94595
4: 8 7 7.59459
5: 9 9 9.24324
6: 11 10 10.8919
7: 13 12 12.5405
8: 14 14 14.1892
9: 16 15 15.8378
10: 17 17 17.4865
11: 19 19 19.1351
12: 21 20 20.7838
13: 22 22 22.4324
14: 24 24 24.0811
15: 26 25 25.7297
16: 27 27 27.3784
17: 29 29 29.027
18: 31 30 30.6757
19: 32 32 32.3243
20: 34 33 33.973
21: 36 35 35.6216
22: 37 37 37.2703
23: 39 38 38.9189
24: 41 40 40.5676
25: 42 42 42.2162
26: 44 43 43.8649
27: 46 45 45.5135
28: 47 47 47.1622
29: 49 48 48.8108
30: 50 50 50.4595
31: 52 52 52.1081
32: 54 53 53.7568
33: 55 55 55.4054
34: 57 57 57.0541
35: 59 58 58.7027
36: 60 60 60.3514
37: 62 62 62
38: 64 63 63.6486
39: 65 65 65.2973
40: 67 66 66.9459
41: 69 68 68.5946
42: 70 70 70.2432
43: 72 71 71.8919
44: 74 73 73.5405
45: 75 75 75.1892
46: 77 76 76.8378
47: 78 78 78.4865
48: 80 80 80.1351
49: 82 81 81.7838
50: 83 83 83.4324
51: 85 85 85.0811
52: 87 86 86.7297
53: 88 88 88.3784
54: 90 90 90.027
55: 92 91 91.6757
56: 93 93 93.3243
57: 95 94 94.973
58: 97 96 96.6216
59: 98 98 98.2703
60: 100 99 99.9189
61: 102 101 101.568
62: 103 103 103.216
63: 105 104 104.865
64: 107 106 106.514
65: 108 108 108.162
66: 110 109 109.811
67: 111 111 111.459
68: 113 113 113.108
69: 115 114 114.757
70: 116 116 116.405
71: 118 118 118.054
72: 120 119 119.703
73: 121 121 121.351
74: 123 123 123


You can e-mail comments to the author.

Back