1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef STARTREK_FIXEDINT_H
24 #define STARTREK_FIXEDINT_H
25 
26 #include "common/serializer.h"
27 
28 #include "startrek/common.h"
29 
30 namespace StarTrek {
31 
32 /**
33  * Signed fixed-point number.
34  */
35 template<typename T, uint totalBits, uint decimalBits>
36 class TFixedInt : Common::Serializable {
37 	static const int max = (1 << (totalBits - decimalBits - 1)) - 1;
38 	static const int min = -max - 1;
39 
40 	T val;
41 
42 public:
fromRaw(T raw)43 	static TFixedInt fromRaw(T raw) {
44 		TFixedInt ret;
45 		ret.val = raw;
46 		return ret;
47 	}
48 
TFixedInt()49 	TFixedInt() : val(0) {}
TFixedInt(double d)50 	TFixedInt(double d) {
51 		assert(d >= min && d <= max); // FIXME: downgrade this to a warning?
52 		val = (T)(d * (1 << decimalBits));
53 	}
54 
55 	/**
56 	 * Constructor from other fixed-point formats.
57 	 */
58 	template<typename T2, uint otherTB, uint otherDB>
59 	explicit TFixedInt<T, totalBits, decimalBits>(const TFixedInt<T2, otherTB, otherDB> &fi) {
60 		int diff = otherDB - decimalBits;
61 		if (otherDB >= decimalBits)
62 			val = fi.raw() >> diff;
63 		else
64 			val = fi.raw() << (-diff);
65 	}
66 
raw()67 	T raw() const {
68 		return val;
69 	}
70 
toInt()71 	int16 toInt() const {
72 		return val >> decimalBits;
73 	}
74 
toDouble()75 	double toDouble() const {
76 		return ((double)val) / (1 << decimalBits);
77 	}
78 
79 	TFixedInt operator-() const {
80 		return fromRaw(-val);
81 	}
82 
83 	/**
84 	 * Multiplication with an int, with the result being an int. Use this if the result
85 	 * might exceed the capacity of this type.
86 	 */
multToInt(int32 i)87 	int16 multToInt(int32 i) {
88 		return ((int32)(val * i)) >> decimalBits;
89 	}
90 
91 	/**
92 	 * Multiplication with an int, with the result being the same type.
93 	 */
94 	TFixedInt operator*(int32 i) const {
95 		return fromRaw(val * i);
96 	}
97 	/**
98 	 * Multiplication with a FixedInt, with the result being the same type.
99 	 */
100 	TFixedInt operator*(const TFixedInt &f) const {
101 		return fromRaw(((int32)(val * f.val)) >> decimalBits);
102 	}
103 	/**
104 	 * Division with an int, with the result being the same type.
105 	 */
106 	TFixedInt operator/(int32 i) const {
107 		return fromRaw(val / i);
108 	}
109 	TFixedInt operator+(const TFixedInt &f) const {
110 		return fromRaw(val + f.val);
111 	}
112 	TFixedInt operator-(const TFixedInt &f) const {
113 		return fromRaw(val - f.val);
114 	}
115 
116 	void operator+=(const TFixedInt &f) {
117 		val += f.val;
118 	}
119 	void operator-=(const TFixedInt &f) {
120 		val -= f.val;
121 	}
122 
123 	bool operator==(double d) const {
124 		return toDouble() == d;
125 	}
126 	bool operator!=(double d) const {
127 		return toDouble() != d;
128 	}
129 	bool operator<(double d) const {
130 		return toDouble() < d;
131 	}
132 	bool operator<=(double d) const {
133 		return toDouble() <= d;
134 	}
135 	bool operator>(double d) const {
136 		return toDouble() > d;
137 	}
138 	bool operator>=(double d) const {
139 		return toDouble() >= d;
140 	}
141 
142 	bool operator==(const TFixedInt &f) const {
143 		return val == f.val;
144 	}
145 	bool operator!=(const TFixedInt &f) const {
146 		return val != f.val;
147 	}
148 	bool operator<(const TFixedInt &f) const {
149 		return val < f.val;
150 	}
151 	bool operator<=(const TFixedInt &f) const {
152 		return val <= f.val;
153 	}
154 	bool operator>(const TFixedInt &f) const {
155 		return val > f.val;
156 	}
157 	bool operator>=(const TFixedInt &f) const {
158 		return val >= f.val;
159 	}
160 
saveLoadWithSerializer(Common::Serializer & ser)161 	void saveLoadWithSerializer(Common::Serializer &ser) {
162 		if (totalBits == 16)
163 			ser.syncAsSint16LE(val);
164 		else if (totalBits == 32)
165 			ser.syncAsSint32LE(val);
166 		else
167 			error("Unsupported bit size for TFixedInt");
168 	}
169 };
170 
171 template<typename T, uint totalBits, uint decimalBits>
172 int32 operator*(const int16 lhs, const TFixedInt<T, totalBits, decimalBits> &rhs) {
173 	return rhs * lhs;
174 }
175 
176 
177 // Fixed-point (2.14) number (between -1 and 1)
178 typedef TFixedInt<int16, 16, 14> Fixed14;
179 
180 // Fixed-point (8.8) number
181 typedef TFixedInt<int16, 16, 8> Fixed8;
182 
183 // Fixed-point (16.16) number
184 typedef TFixedInt<int32, 32, 16> Fixed16;
185 
186 typedef Fixed8 Angle;
187 
188 } // End of namespace StarTrek
189 
190 #endif
191