aboutsummaryrefslogtreecommitdiff
path: root/src/jtutil/cpm_map.hh
blob: 783bc76edcce1547d44f99872106a23052dedb08 (plain)
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_;
	};