1 | /* |
2 | Qalculate |
3 | |
4 | Copyright (C) 2003-2007 Niklas Knutsson (nq@altern.org) |
5 | |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. |
10 | */ |
11 | |
12 | #ifndef UNIT_H |
13 | #define UNIT_H |
14 | |
15 | /** @file */ |
16 | |
17 | /// Type of unit |
18 | typedef enum { |
19 | /// class Unit |
20 | SUBTYPE_BASE_UNIT, |
21 | /// class AliasUnit |
22 | SUBTYPE_ALIAS_UNIT, |
23 | /// class CompositeUnit |
24 | SUBTYPE_COMPOSITE_UNIT |
25 | } UnitSubtype; |
26 | |
27 | #include <libqalculate/ExpressionItem.h> |
28 | #include <libqalculate/includes.h> |
29 | |
30 | /// A unit for measurement. |
31 | /** |
32 | * The Unit class both represents a base unit and is the base class for other unit types. |
33 | * Base units are units defined as basis for other units. Meters and seconds are typical base units. |
34 | * |
35 | * For base units, a name is all that is needed. |
36 | * Base units do however normally have three different names defined for use in expressions - abbreviation (ex. "m"), singular ("meter") and plural ("meters"). |
37 | */ |
38 | class Unit : public ExpressionItem { |
39 | |
40 | protected: |
41 | |
42 | string ssystem; |
43 | bool b_si; |
44 | |
45 | public: |
46 | |
47 | Unit(string cat_, string name_, string plural_ = "" , string singular_ = "" , string title_ = "" , bool is_local = true, bool is_builtin = false, bool is_active = true); |
48 | Unit(); |
49 | Unit(const Unit *unit); |
50 | virtual ~Unit(); |
51 | |
52 | virtual ExpressionItem *copy() const; |
53 | virtual void set(const ExpressionItem *item); |
54 | |
55 | /** Returns if the unit is part of the SI standard. |
56 | * |
57 | * @returns true if the unit is part of the SI standard. |
58 | */ |
59 | bool isSIUnit() const; |
60 | /** State that the unit is part of the SI standard. |
61 | * Sets system to "SI". |
62 | */ |
63 | void setAsSIUnit(); |
64 | /** Sets which system/standard ("SI", "SGC", etc.) the unit is part of. |
65 | * Setting system to "SI" (case-insensitive), is equivalent to setAsSIUnit(). |
66 | */ |
67 | void setSystem(string s_system); |
68 | /** Returns the system/standard that the unit is part of. |
69 | * |
70 | * @returns System string. |
71 | */ |
72 | const string &system() const; |
73 | /** Returns if the unit is a currency (Euro is base unit). |
74 | * |
75 | * @returns true if the unit is a currency. |
76 | */ |
77 | bool isCurrency() const; |
78 | /** Returns a display string representing the unit in an expression. |
79 | * |
80 | * Equivalent to preferredName() for Unit and AliasUnit, but closer to MathStructure::print() for CompositeUnit (prints out base expression). |
81 | */ |
82 | virtual string print(bool plural_, bool short_, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
83 | virtual const string &plural(bool return_singular_if_no_plural = true, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
84 | virtual const string &singular(bool return_abbreviation_if_no_singular = true, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
85 | virtual const string &abbreviation(bool return_singular_if_no_abbreviation = true, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
86 | virtual bool isUsedByOtherUnits() const; |
87 | virtual Unit* baseUnit() const; |
88 | virtual MathStructure &convertToBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
89 | virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
90 | virtual MathStructure &convertToBaseUnit(MathStructure &mvalue) const; |
91 | virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue) const; |
92 | virtual MathStructure convertToBaseUnit() const; |
93 | virtual MathStructure convertFromBaseUnit() const; |
94 | virtual int baseExponent(int exp = 1) const; |
95 | virtual int type() const; |
96 | /** Returns the subtype of the unit, corresponding to which subsubclass the object belongs to. |
97 | * |
98 | * @returns ::UnitSubtype. |
99 | */ |
100 | virtual int subtype() const; |
101 | /** If specified unit is a base unit for this unit, directly or with other units in between. |
102 | * Equivalent to u->isParentOf(this). |
103 | */ |
104 | virtual bool isChildOf(Unit *u) const; |
105 | /** If this unit is a base unit for specified unit, directly or with other units in between. |
106 | * Equivalent to u->isChildOf(this). |
107 | */ |
108 | virtual bool isParentOf(Unit *u) const; |
109 | virtual bool hasComplexRelationTo(Unit *u) const; |
110 | /** Converts a value from specified unit and exponent to this unit. |
111 | * value * (unit^exponent) = new value * (this^new exponent) |
112 | * This function cannot convert to or from CompositeUnit. |
113 | * |
114 | * @param u Unit to convert from. |
115 | * @param[in,out] mvalue Quantity value. |
116 | * @param[in,out] exp Exponent. |
117 | * @returns true if the value was successfully converted. |
118 | */ |
119 | bool convert(Unit *u, MathStructure &mvalue, MathStructure &exp) const; |
120 | /** Converts a value from specified unit and exponent to this unit. |
121 | * value * unit = new value * this |
122 | * This function cannot convert to or from CompositeUnit. |
123 | * |
124 | * @param u Unit to convert from. |
125 | * @param[in,out] mvalue Quantity value. |
126 | * @returns true if the value was successfully converted. |
127 | */ |
128 | bool convert(Unit *u, MathStructure &mvalue) const; |
129 | MathStructure convert(Unit *u, bool *converted = NULL) const; |
130 | |
131 | }; |
132 | |
133 | |
134 | /// An unit with relation to another unit |
135 | /** |
136 | * Alias units is defined in relation to another unit. |
137 | * For example, hour are defined as an alias unit that equals 60 minutes which in turn is defined in relation to seconds. |
138 | * |
139 | * Alias units have an associated base unit, exponent and relation expression. |
140 | * For more complex relations an inverse relation can also be specified for conversion back from the base unit. |
141 | * The base unit must not necessarily be of the base unit class and it is recommended that an alias unit is defined in relation to the closest unit |
142 | * (ex. 1ft = 3 hands, 1 hand = 4 in, and 1 in = 0.0254 m). |
143 | * |
144 | * The relation is usually just a number that tells how large quantity of the base unit is needed to get the alias unit (alias unit = base unit * relation). |
145 | * More complex units can specify the relation as a full-blown expression where '\x' is replaced by the quantity of the base unit and |
146 | * '\y' is the exponent. |
147 | * For example, Degrees Celsius has the relation "\x + 273.15" and the inverse relation "\x - 273.15" to the base unit Kelvin. |
148 | * For simple relations, the reversion is automatic and ought not be defined separately. |
149 | * |
150 | * The precision property inherited from ExpressionItem defines the precision of the relation. |
151 | * |
152 | * The exponent defines the exponential relation to the base unit, so that the alias unit equals the base unit raised to the exponent. |
153 | * For simple unit relations this gives: alias unit = relation * base unit^exponent. |
154 | * |
155 | * Alias units normally have three different names defined for use in expressions - abbreviation (ex. "m"), singular ("meter") and plural ("meters"). |
156 | */ |
157 | class AliasUnit : public Unit { |
158 | |
159 | protected: |
160 | |
161 | string svalue, sinverse; |
162 | int i_exp; |
163 | Unit *o_unit; |
164 | |
165 | public: |
166 | |
167 | AliasUnit(string cat_, string name_, string plural_, string singular_, string title_, Unit *alias, string relation = "1" , int exp = 1, string inverse = "" , bool is_local = true, bool is_builtin = false, bool is_active = true); |
168 | AliasUnit(const AliasUnit *unit); |
169 | AliasUnit(); |
170 | virtual ~AliasUnit(); |
171 | |
172 | virtual ExpressionItem *copy() const; |
173 | virtual void set(const ExpressionItem *item); |
174 | |
175 | virtual Unit* baseUnit() const; |
176 | virtual Unit* firstBaseUnit() const; |
177 | virtual void setBaseUnit(Unit *alias); |
178 | virtual string expression() const; |
179 | virtual string inverseExpression() const; |
180 | /** |
181 | * Sets the relation expression. |
182 | */ |
183 | virtual void setExpression(string relation); |
184 | /** |
185 | * Sets the inverse relation expression. |
186 | */ |
187 | virtual void setInverseExpression(string inverse); |
188 | virtual MathStructure &convertToFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
189 | virtual MathStructure &convertFromFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
190 | virtual MathStructure &convertToBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
191 | virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
192 | virtual MathStructure &convertToBaseUnit(MathStructure &mvalue) const; |
193 | virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue) const; |
194 | virtual MathStructure convertToBaseUnit() const; |
195 | virtual MathStructure convertFromBaseUnit() const; |
196 | virtual int baseExponent(int exp = 1) const; |
197 | virtual void setExponent(int exp); |
198 | virtual int firstBaseExponent() const; |
199 | virtual int subtype() const; |
200 | virtual bool isChildOf(Unit *u) const; |
201 | virtual bool isParentOf(Unit *u) const; |
202 | virtual bool hasComplexExpression() const; |
203 | virtual bool hasComplexRelationTo(Unit *u) const; |
204 | |
205 | }; |
206 | |
207 | /// A subunit in a CompositeUnit |
208 | /** |
209 | * Should normally not be used directly. |
210 | */ |
211 | class AliasUnit_Composite : public AliasUnit { |
212 | |
213 | protected: |
214 | |
215 | Prefix *prefixv; |
216 | |
217 | public: |
218 | |
219 | AliasUnit_Composite(Unit *alias, int exp = 1, Prefix *prefix_ = NULL); |
220 | AliasUnit_Composite(const AliasUnit_Composite *unit); |
221 | virtual ~AliasUnit_Composite(); |
222 | |
223 | virtual ExpressionItem *copy() const; |
224 | virtual void set(const ExpressionItem *item); |
225 | |
226 | virtual string print(bool plural_, bool short_, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
227 | virtual Prefix *prefix() const; |
228 | virtual int prefixExponent() const; |
229 | virtual void set(Unit *u, int exp = 1, Prefix *prefix_ = NULL); |
230 | virtual MathStructure &convertToFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
231 | virtual MathStructure &convertFromFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const; |
232 | |
233 | }; |
234 | |
235 | /// A unit consisting of a number of other units |
236 | /** |
237 | * Composite units are defined by a unit expression with multiple units. |
238 | * Composite units often have an alias unit associated with them, as they do not have a reference name on their own. |
239 | * For example, a joule is defined as an alias defined in relation to a composite unit defined as "Newton * meter". |
240 | * |
241 | * The names of composite units is only used to reference the unit in definitions of other units. |
242 | * They can not be used in expressions. |
243 | * |
244 | * Composite units is definited as a composition of units. |
245 | * The units, with prefixes and exponents, can either be added one by one with add() or |
246 | * parsed from an expression (ex. "cm^3/g) with setBaseExpression(). |
247 | */ |
248 | class CompositeUnit : public Unit { |
249 | |
250 | protected: |
251 | |
252 | string sshort; |
253 | vector<AliasUnit_Composite*> units; |
254 | |
255 | public: |
256 | |
257 | CompositeUnit(string cat_, string name_, string title_ = "" , string base_expression_ = "" , bool is_local = true, bool is_builtin = false, bool is_active = true); |
258 | CompositeUnit(const CompositeUnit *unit); |
259 | virtual ~CompositeUnit(); |
260 | virtual ExpressionItem *copy() const; |
261 | virtual void set(const ExpressionItem *item); |
262 | /** Adds a sub/base unit with specified exponent and an optional prefix. |
263 | * |
264 | * @param u Unit. |
265 | * @param exp Exponent. |
266 | * @param prefix Prefix. |
267 | */ |
268 | virtual void add(Unit *u, int exp = 1, Prefix *prefix = NULL); |
269 | /** Retrieves information about a sub/base unit |
270 | * |
271 | * @param index Index starting at 1. |
272 | * @param[out] exp Exponent. |
273 | * @param[out] prefix Prefix. |
274 | * @returns Sub/base unit (AliasUnit_Composite::firstBaseUnit()). |
275 | */ |
276 | virtual Unit *get(size_t index, int *exp = NULL, Prefix **prefix = NULL) const; |
277 | virtual void setExponent(size_t index, int exp); |
278 | virtual void setPrefix(size_t index, Prefix *prefix); |
279 | /** Returns the number of sub/base units */ |
280 | virtual size_t countUnits() const; |
281 | virtual size_t find(Unit *u) const; |
282 | virtual void del(size_t index); |
283 | /** Prints out the sub/base units with prefixes and exponents. |
284 | * This is the representation of the unit in expressions. |
285 | */ |
286 | virtual string print(bool plural_, bool short_, bool use_unicode = false, bool (*can_display_unicode_string_function) (const char*, void*) = NULL, void *can_display_unicode_string_arg = NULL) const; |
287 | virtual int subtype() const; |
288 | /** If this unit contains a sub/base unit with a relation to the specified unit. |
289 | */ |
290 | virtual bool containsRelativeTo(Unit *u) const; |
291 | /** Creates a MathStructure with the sub/base units of the unit. |
292 | */ |
293 | virtual MathStructure generateMathStructure(bool make_division = false) const; |
294 | virtual void setBaseExpression(string base_expression_); |
295 | /** Removes all sub/base units. */ |
296 | virtual void clear(); |
297 | }; |
298 | |
299 | |
300 | #endif |
301 | |