1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// cpm_map.hh -- "integer +/-" mapping i --> j = const +/- i
// $Id$
//
// cpm_map - "integer +/-" mapping
//
//
// prerequisites
// <assert.h>
// "jt/util++.hh" // for jtutil::how_many_in_range()
//
//
// This class represents a unit-slope linear integer mapping
// i --> j = const +/- i
//
#ifndef NDEBUG
//
// Full bounds checking is done on the mapping in both directions.
//
#endif
//******************************************************************************
class cpm_map
{
public:
// bounds info -- domain
int min_i() const { return min_i_; }
int max_i() const { return max_i_; }
int N_points() const
{ return jtutil::how_many_in_range(min_i_,max_i_); }
bool in_domain(int i) const { return i >= min_i() && i <= max_i(); }
// is the mapping + or - ?
static const bool plus_map = true;
static const bool minus_map = false;
bool sign_flag() const { return sign_; }
int sign() const { return sign_ ? +1 : -1; }
// the mapping itself
int map_unchecked(int i) const
{
return sign_flag() ? offset_ + i
: offset_ - i;
}
int inv_map_unchecked(int j) const
{
return sign_flag() ? j - offset_
: offset_ - j;
}
int map(int i) const
{
assert(in_domain(i));
return map_unchecked(i);
}
int inv_map(int j) const
{
int i = inv_map_unchecked(j);
assert(in_domain(i));
return i;
}
// bounds info -- range
int min_j() const
{
return sign_flag() ? map_unchecked(min_i())
: map_unchecked(max_i());
}
int max_j() const
{
return sign_flag() ? map_unchecked(max_i())
: map_unchecked(min_i());
}
bool in_range(int j) const { return in_domain(inv_map_unchecked(j)); }
//
// constructors
//
// "mirror" map: i --> const - i
// ... map specified by fixed point (must be integer or half-integer)
cpm_map(int min_i_in, int max_i_in,
double fixed_point);
// "shift" map: i --> const + i
// ... map specified by shift amount
// ... default is identity map
cpm_map(int min_i_in, int max_i_in,
int shift_amount = 0)
: min_i_(min_i_in), max_i_(max_i_in),
offset_(shift_amount), sign_(plus_map)
{ }
// generic map: i --> const +/- i
// ... map specified by sample point sample_i --> sample_j
// and by sign (one of {plus,minus}_map )
// ... sample point need *not* be in domain/range
cpm_map(int min_i_in, int max_i_in,
int sample_i, int sample_j,
bool sign_in);
// generic map: i --> const +/- i
// ... map specified by *double* sample point sample_i --> sample_j
// (must specify an integer --> integer mapping)
// and by sign (one of {plus,minus}_map )
// ... hence if sign is minus_map, then sample_i and sample_j
// must both be half-integral
// ... sample point need *not* be in domain/range
cpm_map(int min_i_in, int max_i_in,
double sample_i, double sample_j,
bool sign_in);
// no need for explicit destructor, compiler-generated no-op is ok
// ditto for copy constructor and assignment operator
private:
// bounds (inclusive)
int min_i_, max_i_;
// these define the actual mapping
int offset_;
bool sign_;
};
|