1 /*
2     Qalculate (library)
3 
4     Copyright (C) 2003-2007, 2008, 2016  Hanna Knutsson (hanna.knutsson@protonmail.com)
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 	std::string ssystem, scountries;
43 	bool b_si;
44 	bool b_use_with_prefixes;
45 
46   public:
47 
48 	Unit(std::string cat_, std::string name_, std::string plural_ = "", std::string singular_ = "", std::string title_ = "", bool is_local = true, bool is_builtin = false, bool is_active = true);
49 	Unit();
50 	Unit(const Unit *unit);
51 	virtual ~Unit();
52 
53 	virtual ExpressionItem *copy() const;
54 	virtual void set(const ExpressionItem *item);
55 
56 	/** Returns if the unit is part of the SI standard.
57 	*
58 	* @returns true if the unit is part of the SI standard.
59 	*/
60 	bool isSIUnit() const;
61 	/** State that the unit is part of the SI standard.
62 	* Sets system to "SI".
63 	*/
64 	void setAsSIUnit();
65 	/** Sets which system/standard ("SI", "CGS", etc.) the unit is part of.
66 	* Setting system to "SI" (case-insensitive), is equivalent to setAsSIUnit().
67 	*/
68 	void setSystem(std::string s_system);
69 	/** Returns the system/standard that the unit is part of.
70 	*
71 	* @returns System string.
72 	*/
73 	const std::string &system() const;
74 	/** Returns wether prefixes should be used with this unit or not.
75 	*
76 	* @returns true if the prefixes is appropriate for this unit.
77 	*/
78 	bool useWithPrefixesByDefault() const;
79 	/** Sets wether prefixes are approriate with this unit or not.
80 	*/
81 	void setUseWithPrefixesByDefault(bool use_with_prefixes);
82 	/** Returns if the unit is a currency (Euro is base unit).
83 	*
84 	* @returns true if the unit is a currency.
85 	*/
86 	bool isCurrency() const;
87 	const std::string &countries() const;
88 	void setCountries(std::string country_names);
89 	/** Returns a display string representing the unit in an expression.
90 	*
91 	* Equivalent to preferredName() for Unit and AliasUnit, but closer to MathStructure::print() for CompositeUnit (prints out base expression).
92 	*/
93 	virtual std::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;
94 	virtual const std::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;
95 	virtual const std::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;
96 	virtual const std::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;
97 	virtual bool isUsedByOtherUnits() const;
98 	virtual Unit* baseUnit() const;
99 	virtual MathStructure &convertToBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
100 	virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
101 	virtual MathStructure &convertToBaseUnit(MathStructure &mvalue) const;
102 	virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue) const;
103 	virtual MathStructure convertToBaseUnit() const;
104 	virtual MathStructure convertFromBaseUnit() const;
105 	virtual int baseExponent(int exp = 1) const;
106 	virtual int type() const;
107 	/** Returns the subtype of the unit, corresponding to which subsubclass the object belongs to.
108 	*
109 	* @returns ::UnitSubtype.
110 	*/
111 	virtual int subtype() const;
112 	/** If specified unit is a base unit for this unit, directly or with other units in between.
113 	* Equivalent to u->isParentOf(this).
114 	*/
115 	virtual bool isChildOf(Unit *u) const;
116 	/** If this unit is a base unit for specified unit, directly or with other units in between.
117 	* Equivalent to u->isChildOf(this).
118 	*/
119 	virtual bool isParentOf(Unit *u) const;
120 	virtual bool hasNonlinearRelationTo(Unit *u) const;
121 	virtual bool hasApproximateRelationTo(Unit *u, bool check_variables = false, bool ignore_high_precision_intervals = false) const;
122 	virtual bool containsRelativeTo(Unit *u) const;
123 	virtual bool hasNonlinearRelationToBase() const;
124 	virtual bool hasApproximateRelationToBase(bool check_variables = false, bool ignore_high_precision_intervals = false) const;
125 	/** Converts a value from specified unit and exponent to this unit.
126 	* value * (unit^exponent) = new value * (this^new exponent)
127 	* This function cannot convert to or from CompositeUnit.
128 	*
129 	* @param u Unit to convert from.
130 	* @param[in,out] mvalue Quantity value.
131 	* @param[in,out] exp Exponent.
132 	* @returns true if the value was successfully converted.
133 	*/
134 	bool convert(Unit *u, MathStructure &mvalue, MathStructure &exp) const;
135 	/** Converts a value from specified unit and exponent to this unit.
136 	* value * unit = new value * this
137 	* This function cannot convert to or from CompositeUnit.
138 	*
139 	* @param u Unit to convert from.
140 	* @param[in,out] mvalue Quantity value.
141 	* @returns true if the value was successfully converted.
142 	*/
143 	bool convert(Unit *u, MathStructure &mvalue) const;
144 	MathStructure convert(Unit *u, bool *converted = NULL) const;
145 
146 };
147 
148 
149 /// An unit with relation to another unit
150 /**
151 * Alias units is defined in relation to another unit.
152 * For example, hour are defined as an alias unit that equals 60 minutes which in turn is defined in relation to seconds.
153 *
154 * Alias units have an associated base unit, exponent and relation expression.
155 * For more complex relations an inverse relation can also be specified for conversion back from the base unit.
156 * 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
157 * (ex. 1ft = 3 hands, 1 hand = 4 in, and 1 in = 0.0254 m).
158 *
159 * 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).
160 * More complex units can specify the relation as a full-blown expression where '\x' is replaced by the quantity of the base unit and
161 * '\y' is the exponent.
162 * For example, Degrees Celsius has the relation "\x + 273.15" and the inverse relation "\x - 273.15" to the base unit Kelvin.
163 * For simple relations, the reversion is automatic and ought not be defined separately.
164 *
165 * The precision property inherited from ExpressionItem defines the precision of the relation.
166 *
167 * The exponent defines the exponential relation to the base unit, so that the alias unit equals the base unit raised to the exponent.
168 * For simple unit relations this gives: alias unit = relation * base unit^exponent.
169 *
170 * Alias units normally have three different names defined for use in expressions - abbreviation (ex. "m"), singular ("meter") and plural ("meters").
171 */
172 class AliasUnit : public Unit {
173 
174   protected:
175 
176 	std::string svalue, sinverse, suncertainty;
177 	bool b_relative_uncertainty;
178 	int i_exp, i_mix, i_mix_min;
179 	Unit *o_unit;
180 
181   public:
182 
183 	AliasUnit(std::string cat_, std::string name_, std::string plural_, std::string singular_, std::string title_, Unit *alias, std::string relation = "1", int exp = 1, std::string inverse = "", bool is_local = true, bool is_builtin = false, bool is_active = true);
184 	AliasUnit(const AliasUnit *unit);
185 	AliasUnit();
186 	virtual ~AliasUnit();
187 
188 	virtual ExpressionItem *copy() const;
189 	virtual void set(const ExpressionItem *item);
190 
191 	virtual Unit* baseUnit() const;
192 	virtual Unit* firstBaseUnit() const;
193 	virtual void setBaseUnit(Unit *alias);
194 	virtual std::string expression() const;
195 	virtual std::string inverseExpression() const;
196 	virtual std::string uncertainty(bool *is_relative = NULL) const;
197 	/**
198 	* Sets the relation expression.
199 	*/
200 	virtual void setExpression(std::string relation);
201 	/**
202 	* Sets the inverse relation expression.
203 	*/
204 	virtual void setInverseExpression(std::string inverse);
205 	virtual void setUncertainty(std::string standard_uncertainty, bool is_relative = false);
206 	virtual MathStructure &convertToFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
207 	virtual MathStructure &convertFromFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
208 	virtual MathStructure &convertToBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
209 	virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
210 	virtual MathStructure &convertToBaseUnit(MathStructure &mvalue) const;
211 	virtual MathStructure &convertFromBaseUnit(MathStructure &mvalue) const;
212 	virtual MathStructure convertToBaseUnit() const;
213 	virtual MathStructure convertFromBaseUnit() const;
214 	virtual int baseExponent(int exp = 1) const;
215 	virtual void setExponent(int exp);
216 	virtual int firstBaseExponent() const;
217 	virtual int mixWithBase() const;
218 	virtual int mixWithBaseMinimum() const;
219 	virtual void setMixWithBase(int combine_priority = 1);
220 	virtual void setMixWithBaseMinimum(int combine_minimum);
221 	virtual int subtype() const;
222 	virtual bool isChildOf(Unit *u) const;
223 	virtual bool isParentOf(Unit *u) const;
224 	virtual bool hasNonlinearExpression() const;
225 	virtual bool hasNonlinearRelationTo(Unit *u) const;
226 	virtual bool hasApproximateExpression(bool check_variables = false, bool ignore_high_precision_intervals = false) const;
227 	virtual bool hasApproximateRelationTo(Unit *u, bool check_variables = false, bool ignore_high_precision_intervals = false) const;
228 	virtual bool containsRelativeTo(Unit *u) const;
229 	virtual bool hasNonlinearRelationToBase() const;
230 	virtual bool hasApproximateRelationToBase(bool check_variables = false, bool ignore_high_precision_intervals = false) const;
231 
232 };
233 
234 /// A subunit in a CompositeUnit
235 /**
236 * Should normally not be used directly.
237 */
238 class AliasUnit_Composite : public AliasUnit {
239 
240   protected:
241 
242 	Prefix *prefixv;
243 
244   public:
245 
246 	AliasUnit_Composite(Unit *alias, int exp = 1, Prefix *prefix_ = NULL);
247 	AliasUnit_Composite(const AliasUnit_Composite *unit);
248 	virtual ~AliasUnit_Composite();
249 
250 	virtual ExpressionItem *copy() const;
251 	virtual void set(const ExpressionItem *item);
252 
253 	virtual std::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;
254 	virtual Prefix *prefix() const;
255 	virtual int prefixExponent() const;
256 	virtual void set(Unit *u, int exp = 1, Prefix *prefix_ = NULL);
257 	virtual MathStructure &convertToFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
258 	virtual MathStructure &convertFromFirstBaseUnit(MathStructure &mvalue, MathStructure &mexp) const;
259 
260 };
261 
262 /// A unit consisting of a number of other units
263 /**
264 * Composite units are defined by a unit expression with multiple units.
265 * Composite units often have an alias unit associated with them, as they do not have a reference name on their own.
266 * For example, a joule is defined as an alias defined in relation to a composite unit defined as "Newton * meter".
267 *
268 * The names of composite units is only used to reference the unit in definitions of other units.
269 * They can not be used in expressions.
270 *
271 * Composite units is definited as a composition of units.
272 * The units, with prefixes and exponents, can either be added one by one with add() or
273 * parsed from an expression (ex. "cm^3/g) with setBaseExpression().
274 */
275 class CompositeUnit : public Unit {
276 
277 	protected:
278 
279 		std::string sshort;
280 		std::vector<AliasUnit_Composite*> units;
281 
282 	public:
283 
284 		CompositeUnit(std::string cat_, std::string name_, std::string title_ = "", std::string base_expression_ = "", bool is_local = true, bool is_builtin = false, bool is_active = true);
285 		CompositeUnit(const CompositeUnit *unit);
286 		virtual ~CompositeUnit();
287 		virtual ExpressionItem *copy() const;
288 		virtual void set(const ExpressionItem *item);
289 		/** Adds a sub/base unit with specified exponent and an optional prefix.
290 		*
291 		* @param u Unit.
292 		* @param exp Exponent.
293 		* @param prefix Prefix.
294 		*/
295 		virtual void add(Unit *u, int exp = 1, Prefix *prefix = NULL);
296 		/** Retrieves information about a sub/base unit
297 		*
298 		* @param index Index starting at 1.
299 		* @param[out] exp Exponent.
300 		* @param[out] prefix Prefix.
301 		* @returns Sub/base unit (AliasUnit_Composite::firstBaseUnit()).
302 		*/
303 		virtual Unit *get(size_t index, int *exp = NULL, Prefix **prefix = NULL) const;
304 		virtual void setExponent(size_t index, int exp);
305 		virtual void setPrefix(size_t index, Prefix *prefix);
306 		/** Returns the number of sub/base units */
307 		virtual size_t countUnits() const;
308 		virtual size_t find(Unit *u) const;
309 		virtual void del(size_t index);
310 		/** Prints out the sub/base units with prefixes and exponents.
311 		* This is the representation of the unit in expressions.
312 		*/
313 		virtual std::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;
314 		virtual int subtype() const;
315 		/** If this unit contains a sub/base unit with a relation to the specified unit.
316 		 */
317 		virtual bool containsRelativeTo(Unit *u) const;
318 		virtual bool hasNonlinearRelationToBase() const;
319 		virtual bool hasApproximateRelationToBase(bool check_variables = false, bool ignore_high_precision_intervals = false) const;
320 		/** Creates a MathStructure with the sub/base units of the unit.
321 		*/
322 		virtual MathStructure generateMathStructure(bool make_division = false, bool set_null_prefixes = false) const;
323 		virtual void setBaseExpression(std::string base_expression_);
324 		/** Removes all sub/base units. */
325 		virtual void clear();
326 };
327 
328 
329 #endif
330