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