@@ -72,11 +72,67 @@ long secureRandom(long howsmall, long howbig) {
72
72
}
73
73
74
74
long map (long x, long in_min, long in_max, long out_min, long out_max) {
75
- const long dividend = out_max - out_min;
76
- const long divisor = in_max - in_min;
77
- const long delta = x - in_min;
75
+ const long out_length = out_max - out_min;
76
+ const long in_length = in_max - in_min;
78
77
79
- return (delta * dividend + (divisor / 2 )) / divisor + out_min;
78
+ if (in_length == 0 ) { return in_min; }
79
+
80
+ if (out_length == 0 ) { return out_min; }
81
+
82
+ long delta = x - in_min;
83
+
84
+ if (out_length == in_length) {
85
+ return out_min + delta;
86
+ }
87
+
88
+ if ((out_length < 0 ) && (in_length < 0 )) {
89
+ return map (x, in_max, in_min, out_max, out_min);
90
+ } else if (out_length < 0 ) {
91
+ return map (in_max - delta, in_min, in_max, out_max, out_min);
92
+ } else if (in_length < 0 ) {
93
+ return map (in_max - delta, in_max, in_min, out_min, out_max);
94
+ }
95
+
96
+ // We now know in_min < in_max and out_min < out_max
97
+ // Make sure x is within range of in_min ... in_max
98
+ if ((x < in_min) || (x > in_max)) {
99
+ long shift_factor = 0 ;
100
+
101
+ if (x < in_min) {
102
+ const long before_min = in_min - x;
103
+ shift_factor = -1 - (before_min / in_length);
104
+ } else if (x > in_max) {
105
+ const long passed_max = x - in_max;
106
+ shift_factor = 1 + (passed_max / in_length);
107
+ }
108
+
109
+ if (shift_factor != 0 ) {
110
+ const long in_shift = shift_factor * in_length;
111
+ const long out_shift = shift_factor * out_length;
112
+ in_min += in_shift;
113
+ in_max += in_shift;
114
+ out_min += out_shift;
115
+ out_max += out_shift;
116
+ delta = x - in_min;
117
+ }
118
+ }
119
+
120
+ if (out_length > in_length) {
121
+ // Map to larger range
122
+ const long factor = out_length / in_length;
123
+ const long error_mod = out_length % in_length;
124
+ const long error = (delta * error_mod) / in_length;
125
+ return (delta * factor) + out_min + error;
126
+ }
127
+
128
+ // abs(out_length) < abs(in_length)
129
+ // Map to smaller range
130
+ const long factor = (in_length / out_length);
131
+
132
+ const long estimate_full = in_length / factor + out_min;
133
+ const long error = (delta * (out_max - estimate_full)) / in_length;
134
+
135
+ return delta / factor + out_min + error;
80
136
}
81
137
82
138
uint16_t makeWord (uint16_t w) {
0 commit comments