COPASI API  4.16.103
UnitConversionFactory.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/sbml/UnitConversionFactory.cpp,v $
3 // $Revision: 1.11 $
4 // $Name: $
5 // $Author: ssahle $
6 // $Date: 2012/04/22 15:41:48 $
7 // End CVS Header
8 
9 // Copyright (C) 2012 - 2010 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., University of Heidelberg, and The University
11 // of Manchester.
12 // All rights reserved.
13 
14 // Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
15 // Properties, Inc. and EML Research, gGmbH.
16 // All rights reserved.
17 
18 class UnitDefinition;
19 
20 #include "UnitConversionFactory.hpp"
21 #include "sbml/UnitKind.h"
22 #include <cmath>
23 #include <sstream>
24 
25 /**
26  * The SBML Level that is passed to constructors of unit definitions.
27  */
28 unsigned int UnitConversionFactory::SBML_LEVEL = 2;
29 
30 /**
31  * The SBML Version that is passed to constructors of unit definitions.
32  */
33 unsigned int UnitConversionFactory::SBML_VERSION = 1;
34 
35 /*
36  * Vector that holds the ids for UnitDefinitions that have been created
37  * by the conversion framework so that no two UnitDefinitions produced
38  * have the same id.
39  */
40 std::vector<std::string> UnitConversionFactory::usedIds = std::vector<std::string>();
41 
42 /*
43  * Converts a Unit into the corresponding UnitDefinition that consists
44  * only of SI units.
45  * Possible offsets are ignored.
46  * Freeing the memory for the returned UnitDefinition is up to the
47  * receiver.
48  * On failure a NULL pointer is returned.
49  * @param const Unit& unit
50  * @return UnitDefinition* result
51  */
52 LIBSBML_EXTERN
53 UnitDefinition* UnitConversionFactory::convertToSI(const Unit& unit)
54 {
55  UnitDefinition* pUdef = NULL;
56  Unit* pU = NULL;
57 
58  if (!unit.isSetKind()) return pUdef;
59 
60  UnitKind_t uKind = unit.getKind();
61 
62  switch (uKind)
63  {
64  case UNIT_KIND_AMPERE:
65  pUdef = convertAmpereToSI(unit);
66  break;
67 
68  case UNIT_KIND_BECQUEREL:
69  case UNIT_KIND_HERTZ:
70  pUdef = convertFrequencyToSI(unit);
71  break;
72 
73  case UNIT_KIND_CANDELA:
74  pUdef = convertCandelaToSI(unit);
75  break;
76 
77  case UNIT_KIND_CELSIUS:
78  pUdef = convertCelsiusToSI(unit);
79  break;
80 
81  case UNIT_KIND_COULOMB:
82  pUdef = convertCoulombToSI(unit);
83  break;
84 
85  case UNIT_KIND_DIMENSIONLESS:
86  case UNIT_KIND_ITEM:
87  case UNIT_KIND_RADIAN:
88  case UNIT_KIND_STERADIAN:
89  pUdef = convertDimensionlessToSI(unit);
90  break;
91 
92  case UNIT_KIND_FARAD:
93  pUdef = convertFaradToSI(unit);
94  break;
95 
96  case UNIT_KIND_GRAM:
97  pU = new Unit(unit);
98  pU->setScale(pU->getScale() - 3);
99  pU->setKind(UNIT_KIND_KILOGRAM);
100  pUdef = convertKilogramToSI(*pU);
101  delete pU;
102  break;
103 
104  case UNIT_KIND_GRAY:
105  case UNIT_KIND_SIEVERT:
106  pUdef = convertDoseToSI(unit);
107  break;
108 
109  case UNIT_KIND_HENRY:
110  pUdef = convertHenryToSI(unit);
111  break;
112 
113  case UNIT_KIND_JOULE:
114  pUdef = convertJouleToSI(unit);
115  break;
116 
117  case UNIT_KIND_KATAL:
118  pUdef = convertKatalToSI(unit);
119  break;
120 
121  case UNIT_KIND_KELVIN:
122  pUdef = convertKelvinToSI(unit);
123  break;
124 
125  case UNIT_KIND_KILOGRAM:
126  pUdef = convertKilogramToSI(unit);
127  break;
128 
129  case UNIT_KIND_LITER:
130  case UNIT_KIND_LITRE:
131  pU = new Unit(unit);
132  pU->setKind(UNIT_KIND_METER);
133  pU->setExponent(pU->getExponent()*3);
134  pU->setScale(pU->getScale() - 3);
135  pUdef = convertMeterToSI(*pU);
136  delete pU;
137  break;
138 
139  case UNIT_KIND_LUMEN:
140  pUdef = convertLumenToSI(unit);
141  break;
142 
143  case UNIT_KIND_LUX:
144  pUdef = convertLuxToSI(unit);
145  break;
146 
147  case UNIT_KIND_METER:
148  case UNIT_KIND_METRE:
149  pUdef = convertMeterToSI(unit);
150  break;
151 
152  case UNIT_KIND_MOLE:
153 #if LIBSBML_VERSION >= 40100
154  // this may be not totally correct, but this is the way we currently intend to
155  // handle it in COPASI
156  case UNIT_KIND_AVOGADRO:
157 #endif // LIBSBML_VERSION
158  pUdef = convertMoleToSI(unit);
159  break;
160 
161  case UNIT_KIND_NEWTON:
162  pUdef = convertNewtonToSI(unit);
163  break;
164 
165  case UNIT_KIND_OHM:
166  pUdef = convertOhmToSI(unit);
167  break;
168 
169  case UNIT_KIND_PASCAL:
170  pUdef = convertPascalToSI(unit);
171  break;
172 
173  case UNIT_KIND_SECOND:
174  pUdef = convertSecondToSI(unit);
175  break;
176 
177  case UNIT_KIND_SIEMENS:
178  pUdef = convertSiemensToSI(unit);
179  break;
180 
181  case UNIT_KIND_TESLA:
182  pUdef = convertTeslaToSI(unit);
183  break;
184 
185  case UNIT_KIND_VOLT:
186  pUdef = convertVoltToSI(unit);
187  break;
188 
189  case UNIT_KIND_WATT:
190  pUdef = convertWattToSI(unit);
191  break;
192 
193  case UNIT_KIND_WEBER:
194  pUdef = convertWeberToSI(unit);
195  break;
196 
197  case UNIT_KIND_INVALID:
198  delete pUdef;
199  pUdef = NULL;
200  break;
201  }
202 
203  if (pUdef != NULL)
204  {
205  unsigned int num = 1;
206  std::stringstream ss;
207  ss << "UnitDefinition_" << num;
208 
209  while (!UnitConversionFactory::isIdUnused(ss.str()))
210  {
211  ++num;
212  ss.str("");
213  ss << "UnitDefinition_" << num;
214  }
215 
216  std::string id = ss.str();
217  usedIds.push_back(id);
218  pUdef->setId(id);
219  UnitKind_t uKind = unit.getKind();
220  pUdef->setName(UnitKind_toString(uKind));
221  }
222 
223  return pUdef;
224 }
225 
226 /*
227  * Converts an Ampere Unit into the corresponding UnitDefinition
228  * consisting only of SI units.
229  * If the given unit does not have the correct kind, a NULL pointer is
230  * returned.
231  * It is up to the receiver to free the memory of the returned
232  * UnitDefinition.
233  * @param const Unit& unit
234  * @return UnitDefinition* result
235  */
236 LIBSBML_EXTERN
237 UnitDefinition* UnitConversionFactory::convertAmpereToSI(const Unit& unit)
238 {
239  UnitKind_t uKind = unit.getKind();
240 
241  if (uKind != UNIT_KIND_AMPERE) return NULL;
242 
243  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
244  Unit* pU = new Unit(unit);
245  pU->setOffset(0.0);
246  pUdef->addUnit(pU);
247  delete pU;
248  return pUdef;
249 }
250 
251 /*
252  * Converts a frequency Unit into the corresponding UnitDefinition
253  * consisting only of SI units. This could be e.g. a Hertz or Bequerel unit.
254  * If the given unit does not have the correct kind, a NULL pointer is
255  * returned.
256  * It is up to the receiver to free the memory of the returned
257  * UnitDefinition.
258  * @param const Unit& unit
259  * @return UnitDefinition* result
260  */
261 LIBSBML_EXTERN
262 UnitDefinition* UnitConversionFactory::convertFrequencyToSI(const Unit& unit)
263 {
264  UnitKind_t uKind = unit.getKind();
265 
266  if (uKind != UNIT_KIND_HERTZ && uKind != UNIT_KIND_BECQUEREL) return NULL;
267 
268  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
269  Unit* pU = new Unit(unit);
270  pU->setKind(UNIT_KIND_SECOND);
271  pU->setOffset(0.0);
272  pU->setExponent(-1*pU->getExponent());
273  return pUdef;
274 }
275 
276 /*
277  * Converts a Candela Unit into the corresponding UnitDefinition
278  * consisting only of SI units.
279  * If the given unit does not have the correct kind, a NULL pointer is
280  * returned.
281  * It is up to the receiver to free the memory of the returned
282  * UnitDefinition.
283  * @param const Unit& unit
284  * @return UnitDefinition* result
285  */
286 LIBSBML_EXTERN
287 UnitDefinition* UnitConversionFactory::convertCandelaToSI(const Unit& unit)
288 {
289  UnitKind_t uKind = unit.getKind();
290 
291  if (uKind != UNIT_KIND_CANDELA) return NULL;
292 
293  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
294  Unit* pU = new Unit(unit);
295  pU->setOffset(0.0);
296  pUdef->addUnit(pU);
297  delete pU;
298  return pUdef;
299 }
300 
301 /*
302  * Converts a Celsius Unit into the corresponding UnitDefinition
303  * consisting only of SI units.
304  * If the given unit does not have the correct kind, a NULL pointer is
305  * returned.
306  * It is up to the receiver to free the memory of the returned
307  * UnitDefinition.
308  * @param const Unit& unit
309  * @return UnitDefinition* result
310  */
311 LIBSBML_EXTERN
312 UnitDefinition* UnitConversionFactory::convertCelsiusToSI(const Unit& unit)
313 {
314  UnitKind_t uKind = unit.getKind();
315 
316  if (uKind != UNIT_KIND_CELSIUS) return NULL;
317 
318  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
319  Unit* pU = new Unit(unit);
320  pU->setKind(UNIT_KIND_KELVIN);
321  pU->setOffset(0.0);
322  pUdef->addUnit(pU);
323  delete pU;
324  return pUdef;
325 }
326 
327 /*
328  * Converts a Coulomb Unit into the corresponding UnitDefinition
329  * consisting only of SI units.
330  * If the given unit does not have the correct kind, a NULL pointer is
331  * returned.
332  * It is up to the receiver to free the memory of the returned
333  * UnitDefinition.
334  * @param const Unit& unit
335  * @return UnitDefinition* result
336  */
337 LIBSBML_EXTERN
338 UnitDefinition* UnitConversionFactory::convertCoulombToSI(const Unit& unit)
339 {
340  UnitKind_t uKind = unit.getKind();
341 
342  if (uKind != UNIT_KIND_COULOMB) return NULL;
343 
344  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
345  Unit* pU = new Unit(unit);
346  pU->setKind(UNIT_KIND_AMPERE);
347  pU->setOffset(0.0);
348  pUdef->addUnit(pU);
349  delete pU;
350  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
351  pU->setKind(UNIT_KIND_SECOND);
352  pU->setExponent(unit.getExponent());
353  pUdef->addUnit(pU);
354  delete pU;
355  return pUdef;
356 }
357 
358 /*
359  * Converts a "Dimensionless" Unit into the corresponding UnitDefinition
360  * consisting only of SI units. This would include e.g. the Radian unit.
361  * If the given unit does not have the correct kind, a NULL pointer is
362  * returned.
363  * It is up to the receiver to free the memory of the returned
364  * UnitDefinition.
365  * @param const Unit& unit
366  * @return UnitDefinition* result
367  */
368 LIBSBML_EXTERN
369 UnitDefinition* UnitConversionFactory::convertDimensionlessToSI(const Unit& unit)
370 {
371  UnitKind_t uKind = unit.getKind();
372 
373  if (uKind != UNIT_KIND_DIMENSIONLESS && uKind != UNIT_KIND_ITEM && uKind != UNIT_KIND_RADIAN && uKind != UNIT_KIND_STERADIAN) return NULL;
374 
375  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
376  Unit* pU = new Unit(unit);
377  pU->setKind(UNIT_KIND_DIMENSIONLESS);
378  pU->setOffset(0.0);
379  pUdef->addUnit(pU);
380  delete pU;
381  return pUdef;
382 }
383 
384 /*
385  * Converts a Farad Unit into the corresponding UnitDefinition
386  * consisting only of SI units.
387  * If the given unit does not have the correct kind, a NULL pointer is
388  * returned.
389  * It is up to the receiver to free the memory of the returned
390  * UnitDefinition.
391  * @param const Unit& unit
392  * @return UnitDefinition* result
393  */
394 LIBSBML_EXTERN
395 UnitDefinition* UnitConversionFactory::convertFaradToSI(const Unit& unit)
396 {
397  UnitKind_t uKind = unit.getKind();
398 
399  if (uKind != UNIT_KIND_FARAD) return NULL;
400 
401  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
402  Unit* pU = new Unit(unit);
403  pU->setOffset(0.0);
404  pU->setKind(UNIT_KIND_AMPERE);
405  pU->setExponent(2*unit.getExponent());
406  pUdef->addUnit(pU);
407  delete pU;
408  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
409  pU->setKind(UNIT_KIND_KILOGRAM);
410  pU->setExponent(-1*unit.getExponent());
411  pUdef->addUnit(pU);
412  delete pU;
413  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
414  pU->setKind(UNIT_KIND_METER);
415  pU->setExponent(-2*unit.getExponent());
416  pUdef->addUnit(pU);
417  delete pU;
418  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
419  pU->setKind(UNIT_KIND_SECOND);
420  pU->setExponent(4*unit.getExponent());
421  pUdef->addUnit(pU);
422  delete pU;
423  return pUdef;
424 }
425 
426 /*
427  * Converts a Kilogram Unit into the corresponding UnitDefinition
428  * consisting only of SI units.
429  * If the given unit does not have the correct kind, a NULL pointer is
430  * returned.
431  * It is up to the receiver to free the memory of the returned
432  * UnitDefinition.
433  * @param const Unit& unit
434  * @return UnitDefinition* result
435  */
436 LIBSBML_EXTERN
437 UnitDefinition* UnitConversionFactory::convertKilogramToSI(const Unit& unit)
438 {
439  UnitKind_t uKind = unit.getKind();
440 
441  if (uKind != UNIT_KIND_KILOGRAM) return NULL;
442 
443  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
444  Unit* pU = new Unit(unit);
445  pU->setOffset(0.0);
446  pUdef->addUnit(pU);
447  delete pU;
448  return pUdef;
449 }
450 
451 /*
452  * Converts a dose Unit into the corresponding UnitDefinition
453  * consisting only of SI units.
454  * Dose units are e.g. gray and sievert.
455  * If the given unit does not have the correct kind, a NULL pointer is
456  * returned.
457  * It is up to the receiver to free the memory of the returned
458  * UnitDefinition.
459  * @param const Unit& unit
460  * @return UnitDefinition* result
461  */
462 LIBSBML_EXTERN
463 UnitDefinition* UnitConversionFactory::convertDoseToSI(const Unit& unit)
464 {
465  UnitKind_t uKind = unit.getKind();
466 
467  if (uKind != UNIT_KIND_GRAM && uKind != UNIT_KIND_SIEVERT) return NULL;
468 
469  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
470  Unit* pU = new Unit(unit);
471  pU->setOffset(0.0);
472  pU->setKind(UNIT_KIND_METER);
473  pU->setExponent(2*unit.getExponent());
474  pUdef->addUnit(pU);
475  delete pU;
476  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
477  pU->setKind(UNIT_KIND_SECOND);
478  pU->setExponent(-2*unit.getExponent());
479  pUdef->addUnit(pU);
480  delete pU;
481  return pUdef;
482 }
483 
484 /*
485  * Converts a Henry Unit into the corresponding UnitDefinition
486  * consisting only of SI units.
487  * If the given unit does not have the correct kind, a NULL pointer is
488  * returned.
489  * It is up to the receiver to free the memory of the returned
490  * UnitDefinition.
491  * @param const Unit& unit
492  * @return UnitDefinition* result
493  */
494 LIBSBML_EXTERN
495 UnitDefinition* UnitConversionFactory::convertHenryToSI(const Unit& unit)
496 {
497  UnitKind_t uKind = unit.getKind();
498 
499  if (uKind != UNIT_KIND_HENRY) return NULL;
500 
501  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
502  Unit* pU = new Unit(unit);
503  pU->setOffset(0.0);
504  pU->setKind(UNIT_KIND_AMPERE);
505  pU->setExponent(-2*unit.getExponent());
506  pUdef->addUnit(pU);
507  delete pU;
508  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
509  pU->setKind(UNIT_KIND_KILOGRAM);
510  pU->setExponent(unit.getExponent());
511  pUdef->addUnit(pU);
512  delete pU;
513  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
514  pU->setKind(UNIT_KIND_METER);
515  pU->setExponent(2*unit.getExponent());
516  pUdef->addUnit(pU);
517  delete pU;
518  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
519  pU->setKind(UNIT_KIND_SECOND);
520  pU->setExponent(-2*unit.getExponent());
521  pUdef->addUnit(pU);
522  delete pU;
523  return pUdef;
524 }
525 
526 /*
527  * Converts a Joule Unit into the corresponding UnitDefinition
528  * consisting only of SI units.
529  * If the given unit does not have the correct kind, a NULL pointer is
530  * returned.
531  * It is up to the receiver to free the memory of the returned
532  * UnitDefinition.
533  * @param const Unit& unit
534  * @return UnitDefinition* result
535  */
536 LIBSBML_EXTERN
537 UnitDefinition* UnitConversionFactory::convertJouleToSI(const Unit& unit)
538 {
539  UnitKind_t uKind = unit.getKind();
540 
541  if (uKind != UNIT_KIND_JOULE) return NULL;
542 
543  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
544  Unit* pU = new Unit(unit);
545  pU->setOffset(0.0);
546  pU->setKind(UNIT_KIND_KILOGRAM);
547  pU->setExponent(unit.getExponent());
548  pUdef->addUnit(pU);
549  delete pU;
550  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
551  pU->setKind(UNIT_KIND_METER);
552  pU->setExponent(2*unit.getExponent());
553  pUdef->addUnit(pU);
554  delete pU;
555  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
556  pU->setKind(UNIT_KIND_SECOND);
557  pU->setExponent(-2*unit.getExponent());
558  pUdef->addUnit(pU);
559  delete pU;
560  return pUdef;
561 }
562 
563 /*
564  * Converts a Katal Unit into the corresponding UnitDefinition
565  * consisting only of SI units.
566  * If the given unit does not have the correct kind, a NULL pointer is
567  * returned.
568  * It is up to the receiver to free the memory of the returned
569  * UnitDefinition.
570  * @param const Unit& unit
571  * @return UnitDefinition* result
572  */
573 LIBSBML_EXTERN
574 UnitDefinition* UnitConversionFactory::convertKatalToSI(const Unit& unit)
575 {
576  UnitKind_t uKind = unit.getKind();
577 
578  if (uKind != UNIT_KIND_KATAL) return NULL;
579 
580  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
581  Unit* pU = new Unit(unit);
582  pU->setOffset(0.0);
583  pU->setKind(UNIT_KIND_MOLE);
584  pU->setExponent(unit.getExponent());
585  pUdef->addUnit(pU);
586  delete pU;
587  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
588  pU->setKind(UNIT_KIND_SECOND);
589  pU->setExponent(-1*unit.getExponent());
590  pUdef->addUnit(pU);
591  delete pU;
592  return pUdef;
593 }
594 
595 /*
596  * Converts a Kelvin Unit into the corresponding UnitDefinition
597  * consisting only of SI units.
598  * If the given unit does not have the correct kind, a NULL pointer is
599  * returned.
600  * It is up to the receiver to free the memory of the returned
601  * UnitDefinition.
602  * @param const Unit& unit
603  * @return UnitDefinition* result
604  */
605 LIBSBML_EXTERN
606 UnitDefinition* UnitConversionFactory::convertKelvinToSI(const Unit& unit)
607 {
608  UnitKind_t uKind = unit.getKind();
609 
610  if (uKind != UNIT_KIND_KELVIN) return NULL;
611 
612  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
613  Unit* pU = new Unit(unit);
614  pU->setOffset(0.0);
615  pUdef->addUnit(pU);
616  delete pU;
617  return pUdef;
618 }
619 
620 /*
621  * Converts a Lumen Unit into the corresponding UnitDefinition
622  * consisting only of SI units.
623  * If the given unit does not have the correct kind, a NULL pointer is
624  * returned.
625  * It is up to the receiver to free the memory of the returned
626  * UnitDefinition.
627  * @param const Unit& unit
628  * @return UnitDefinition* result
629  */
630 LIBSBML_EXTERN
631 UnitDefinition* UnitConversionFactory::convertLumenToSI(const Unit& unit)
632 {
633  UnitKind_t uKind = unit.getKind();
634 
635  if (uKind != UNIT_KIND_LUMEN) return NULL;
636 
637  Unit* pU = new Unit(unit);
638  pU->setKind(UNIT_KIND_CANDELA);
639  UnitDefinition* pUdef = convertCandelaToSI(*pU);
640  delete pU;
641  return pUdef;
642 }
643 
644 /*
645  * Converts a Lux Unit into the corresponding UnitDefinition
646  * consisting only of SI units.
647  * If the given unit does not have the correct kind, a NULL pointer is
648  * returned.
649  * It is up to the receiver to free the memory of the returned
650  * UnitDefinition.
651  * @param const Unit& unit
652  * @return UnitDefinition* result
653  */
654 LIBSBML_EXTERN
655 UnitDefinition* UnitConversionFactory::convertLuxToSI(const Unit& unit)
656 {
657  UnitKind_t uKind = unit.getKind();
658 
659  if (uKind != UNIT_KIND_LUX) return NULL;
660 
661  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
662  Unit* pU = new Unit(unit);
663  pU->setKind(UNIT_KIND_CANDELA);
664  pU->setOffset(0.0);
665  pUdef->addUnit(pU);
666  delete pU;
667  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
668  pU->setKind(UNIT_KIND_METER);
669  pU->setExponent(-2*unit.getExponent());
670  pUdef->addUnit(pU);
671  delete pU;
672  return pUdef;
673 }
674 
675 /*
676  * Converts a Meter Unit into the corresponding UnitDefinition
677  * consisting only of SI units.
678  * If the given unit does not have the correct kind, a NULL pointer is
679  * returned.
680  * It is up to the receiver to free the memory of the returned
681  * UnitDefinition.
682  * @param const Unit& unit
683  * @return UnitDefinition* result
684  */
685 LIBSBML_EXTERN
686 UnitDefinition* UnitConversionFactory::convertMeterToSI(const Unit& unit)
687 {
688  UnitKind_t uKind = unit.getKind();
689 
690  if (uKind != UNIT_KIND_METER) return NULL;
691 
692  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
693  Unit* pU = new Unit(unit);
694  pU->setOffset(0.0);
695  pUdef->addUnit(pU);
696  delete pU;
697  return pUdef;
698 }
699 
700 /*
701  * Converts a Mole Unit into the corresponding UnitDefinition
702  * consisting only of SI units.
703  * If the given unit does not have the correct kind, a NULL pointer is
704  * returned.
705  * It is up to the receiver to free the memory of the returned
706  * UnitDefinition.
707  * @param const Unit& unit
708  * @return UnitDefinition* result
709  */
710 LIBSBML_EXTERN
711 UnitDefinition* UnitConversionFactory::convertMoleToSI(const Unit& unit)
712 {
713  UnitKind_t uKind = unit.getKind();
714 
715  if (uKind != UNIT_KIND_MOLE) return NULL;
716 
717  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
718  Unit* pU = new Unit(unit);
719  pU->setOffset(0.0);
720  pUdef->addUnit(pU);
721  delete pU;
722  return pUdef;
723 }
724 
725 /*
726  * Converts a Newton Unit into the corresponding UnitDefinition
727  * consisting only of SI units.
728  * If the given unit does not have the correct kind, a NULL pointer is
729  * returned.
730  * It is up to the receiver to free the memory of the returned
731  * UnitDefinition.
732  * @param const Unit& unit
733  * @return UnitDefinition* result
734  */
735 LIBSBML_EXTERN
736 UnitDefinition* UnitConversionFactory::convertNewtonToSI(const Unit& unit)
737 {
738  UnitKind_t uKind = unit.getKind();
739 
740  if (uKind != UNIT_KIND_NEWTON) return NULL;
741 
742  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
743  Unit* pU = new Unit(unit);
744  pU->setOffset(0.0);
745  pU->setKind(UNIT_KIND_KILOGRAM);
746  pUdef->addUnit(pU);
747  delete pU;
748  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
749  pU->setKind(UNIT_KIND_METER);
750  pU->setExponent(unit.getExponent());
751  pUdef->addUnit(pU);
752  delete pU;
753  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
754  pU->setKind(UNIT_KIND_SECOND);
755  pU->setExponent(-2*unit.getExponent());
756  pUdef->addUnit(pU);
757  delete pU;
758  return pUdef;
759 }
760 
761 /*
762  * Converts a Ohm Unit into the corresponding UnitDefinition
763  * consisting only of SI units.
764  * If the given unit does not have the correct kind, a NULL pointer is
765  * returned.
766  * It is up to the receiver to free the memory of the returned
767  * UnitDefinition.
768  * @param const Unit& unit
769  * @return UnitDefinition* result
770  */
771 LIBSBML_EXTERN
772 UnitDefinition* UnitConversionFactory::convertOhmToSI(const Unit& unit)
773 {
774  UnitKind_t uKind = unit.getKind();
775 
776  if (uKind != UNIT_KIND_OHM) return NULL;
777 
778  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
779  Unit* pU = new Unit(unit);
780  pU->setOffset(0.0);
781  pU->setKind(UNIT_KIND_AMPERE);
782  pU->setExponent(-2*unit.getExponent());
783  pUdef->addUnit(pU);
784  delete pU;
785  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
786  pU->setKind(UNIT_KIND_KILOGRAM);
787  pU->setExponent(unit.getExponent());
788  pUdef->addUnit(pU);
789  delete pU;
790  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
791  pU->setKind(UNIT_KIND_METER);
792  pU->setExponent(2*unit.getExponent());
793  pUdef->addUnit(pU);
794  delete pU;
795  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
796  pU->setKind(UNIT_KIND_SECOND);
797  pU->setExponent(-3*unit.getExponent());
798  pUdef->addUnit(pU);
799  delete pU;
800  return pUdef;
801 }
802 
803 /*
804  * Converts a Pascal Unit into the corresponding UnitDefinition
805  * consisting only of SI units.
806  * If the given unit does not have the correct kind, a NULL pointer is
807  * returned.
808  * It is up to the receiver to free the memory of the returned
809  * UnitDefinition.
810  * @param const Unit& unit
811  * @return UnitDefinition* result
812  */
813 LIBSBML_EXTERN
814 UnitDefinition* UnitConversionFactory::convertPascalToSI(const Unit& unit)
815 {
816  UnitKind_t uKind = unit.getKind();
817 
818  if (uKind != UNIT_KIND_PASCAL) return NULL;
819 
820  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
821  Unit* pU = new Unit(unit);
822  pU->setKind(UNIT_KIND_KILOGRAM);
823  pU->setOffset(0.0);
824  pUdef->addUnit(pU);
825  delete pU;
826  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
827  pU->setKind(UNIT_KIND_METER);
828  pU->setExponent(-1*unit.getExponent());
829  pUdef->addUnit(pU);
830  delete pU;
831  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
832  pU->setKind(UNIT_KIND_SECOND);
833  pU->setExponent(-2*unit.getExponent());
834  pUdef->addUnit(pU);
835  delete pU;
836  return pUdef;
837 }
838 
839 /*
840  * Converts a Second Unit into the corresponding UnitDefinition
841  * consisting only of SI units.
842  * If the given unit does not have the correct kind, a NULL pointer is
843  * returned.
844  * It is up to the receiver to free the memory of the returned
845  * UnitDefinition.
846  * @param const Unit& unit
847  * @return UnitDefinition* result
848  */
849 LIBSBML_EXTERN
850 UnitDefinition* UnitConversionFactory::convertSecondToSI(const Unit& unit)
851 {
852  UnitKind_t uKind = unit.getKind();
853 
854  if (uKind != UNIT_KIND_SECOND) return NULL;
855 
856  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
857  Unit* pU = new Unit(unit);
858  pU->setOffset(0.0);
859  pUdef->addUnit(pU);
860  delete pU;
861  return pUdef;
862 }
863 
864 /*
865  * Converts a Siemens Unit into the corresponding UnitDefinition
866  * consisting only of SI units.
867  * If the given unit does not have the correct kind, a NULL pointer is
868  * returned.
869  * It is up to the receiver to free the memory of the returned
870  * UnitDefinition.
871  * @param const Unit& unit
872  * @return UnitDefinition* result
873  */
874 LIBSBML_EXTERN
875 UnitDefinition* UnitConversionFactory::convertSiemensToSI(const Unit& unit)
876 {
877  UnitKind_t uKind = unit.getKind();
878 
879  if (uKind != UNIT_KIND_SIEMENS) return NULL;
880 
881  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
882  Unit* pU = new Unit(unit);
883  pU->setOffset(0.0);
884  pU->setKind(UNIT_KIND_AMPERE);
885  pU->setExponent(2*unit.getExponent());
886  pUdef->addUnit(pU);
887  delete pU;
888  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
889  pU->setKind(UNIT_KIND_KILOGRAM);
890  pU->setExponent(-1*unit.getExponent());
891  pUdef->addUnit(pU);
892  delete pU;
893  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
894  pU->setKind(UNIT_KIND_METER);
895  pU->setExponent(-2*unit.getExponent());
896  pUdef->addUnit(pU);
897  delete pU;
898  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
899  pU->setKind(UNIT_KIND_SECOND);
900  pU->setExponent(3*unit.getExponent());
901  pUdef->addUnit(pU);
902  delete pU;
903  return pUdef;
904 }
905 
906 /*
907  * Converts a Tesla Unit into the corresponding UnitDefinition
908  * consisting only of SI units.
909  * If the given unit does not have the correct kind, a NULL pointer is
910  * returned.
911  * It is up to the receiver to free the memory of the returned
912  * UnitDefinition.
913  * @param const Unit& unit
914  * @return UnitDefinition* result
915  */
916 LIBSBML_EXTERN
917 UnitDefinition* UnitConversionFactory::convertTeslaToSI(const Unit& unit)
918 {
919  UnitKind_t uKind = unit.getKind();
920 
921  if (uKind != UNIT_KIND_TESLA) return NULL;
922 
923  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
924  Unit* pU = new Unit(unit);
925  pU->setOffset(0.0);
926  pU->setKind(UNIT_KIND_AMPERE);
927  pU->setExponent(-1*unit.getExponent());
928  pUdef->addUnit(pU);
929  delete pU;
930  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
931  pU->setKind(UNIT_KIND_KILOGRAM);
932  pU->setExponent(unit.getExponent());
933  pUdef->addUnit(pU);
934  delete pU;
935  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
936  pU->setKind(UNIT_KIND_SECOND);
937  pU->setExponent(-2*unit.getExponent());
938  pUdef->addUnit(pU);
939  delete pU;
940  return pUdef;
941 }
942 
943 /*
944  * Converts a Volt Unit into the corresponding UnitDefinition
945  * consisting only of SI units.
946  * If the given unit does not have the correct kind, a NULL pointer is
947  * returned.
948  * It is up to the receiver to free the memory of the returned
949  * UnitDefinition.
950  * @param const Unit& unit
951  * @return UnitDefinition* result
952  */
953 LIBSBML_EXTERN
954 UnitDefinition* UnitConversionFactory::convertVoltToSI(const Unit& unit)
955 {
956  UnitKind_t uKind = unit.getKind();
957 
958  if (uKind != UNIT_KIND_VOLT) return NULL;
959 
960  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
961  Unit* pU = new Unit(unit);
962  pU->setOffset(0.0);
963  pU->setKind(UNIT_KIND_AMPERE);
964  pU->setExponent(-1*unit.getExponent());
965  pUdef->addUnit(pU);
966  delete pU;
967  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
968  pU->setKind(UNIT_KIND_KILOGRAM);
969  pU->setExponent(unit.getExponent());
970  pUdef->addUnit(pU);
971  delete pU;
972  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
973  pU->setKind(UNIT_KIND_METER);
974  pU->setExponent(2*unit.getExponent());
975  pUdef->addUnit(pU);
976  delete pU;
977  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
978  pU->setKind(UNIT_KIND_SECOND);
979  pU->setExponent(-3*unit.getExponent());
980  pUdef->addUnit(pU);
981  delete pU;
982  return pUdef;
983 }
984 
985 /*
986  * Converts a Watt Unit into the corresponding UnitDefinition
987  * consisting only of SI units.
988  * If the given unit does not have the correct kind, a NULL pointer is
989  * returned.
990  * It is up to the receiver to free the memory of the returned
991  * UnitDefinition.
992  * @param const Unit& unit
993  * @return UnitDefinition* result
994  */
995 LIBSBML_EXTERN
996 UnitDefinition* UnitConversionFactory::convertWattToSI(const Unit& unit)
997 {
998  UnitKind_t uKind = unit.getKind();
999 
1000  if (uKind != UNIT_KIND_WATT) return NULL;
1001 
1002  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1003  Unit* pU = new Unit(unit);
1004  pU->setOffset(0.0);
1005  pU->setKind(UNIT_KIND_KILOGRAM);
1006  pU->setExponent(unit.getExponent());
1007  pUdef->addUnit(pU);
1008  delete pU;
1009  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1010  pU->setKind(UNIT_KIND_METER);
1011  pU->setExponent(2*unit.getExponent());
1012  pUdef->addUnit(pU);
1013  delete pU;
1014  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1015  pU->setKind(UNIT_KIND_SECOND);
1016  pU->setExponent(-3*unit.getExponent());
1017  pUdef->addUnit(pU);
1018  delete pU;
1019  return pUdef;
1020 }
1021 
1022 /*
1023  * Converts a Weber Unit into the corresponding UnitDefinition
1024  * consisting only of SI units.
1025  * If the given unit does not have the correct kind, a NULL pointer is
1026  * returned.
1027  * It is up to the receiver to free the memory of the returned
1028  * UnitDefinition.
1029  * @param const Unit& unit
1030  * @return UnitDefinition* result
1031  */
1032 LIBSBML_EXTERN
1033 UnitDefinition* UnitConversionFactory::convertWeberToSI(const Unit& unit)
1034 {
1035  UnitKind_t uKind = unit.getKind();
1036 
1037  if (uKind != UNIT_KIND_WATT) return NULL;
1038 
1039  UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1040  Unit* pU = new Unit(unit);
1041  pU->setOffset(0.0);
1042  pU->setKind(UNIT_KIND_AMPERE);
1043  pU->setExponent(-1*unit.getExponent());
1044  pUdef->addUnit(pU);
1045  delete pU;
1046  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1047  pU->setKind(UNIT_KIND_KILOGRAM);
1048  pU->setExponent(unit.getExponent());
1049  pUdef->addUnit(pU);
1050  delete pU;
1051  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1052  pU->setKind(UNIT_KIND_METER);
1053  pU->setExponent(2*unit.getExponent());
1054  pUdef->addUnit(pU);
1055  delete pU;
1056  pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1057  pU->setKind(UNIT_KIND_SECOND);
1058  pU->setExponent(-2*unit.getExponent());
1059  pUdef->addUnit(pU);
1060  delete pU;
1061  return pUdef;
1062 }
1063 
1064 /*
1065  LIBSBML_EXTERN
1066  UnitDefinition* UnitConversionFactory::normalize(const UnitDefinition& uDef)
1067  {
1068 // convert all units to SI units
1069 // see if units other then the first one have a scale and/or a multiplier
1070 // if so, combine those with the scale and/or multiplier of the first unit
1071 UnitDefinition* pResult = NULL;
1072 unsigned int maxUnits = uDef.getNumUnits();
1073 unsigned int counter = 0;
1074 while (counter < maxUnits)
1075 {
1076 Unit* pU = uDef.getUnit(counter);
1077 UnitDefinition* pTempUdef = UnitConversionFactory::convertToSI(*pU);
1078 if (pTempUdef == NULL)
1079 {
1080 pResult = NULL;
1081 break;
1082 }
1083 UnitDefinition* pTempUdef2 = UnitConversionFactory::combine(*pResult, *pTempUdef);
1084 delete pTempUdef;
1085 delete pResult;
1086 pResult = pTempUdef2;
1087 if (pResult == NULL)
1088 {
1089 break;
1090 }
1091 ++counter;
1092 }
1093 if (pResult != NULL)
1094 {
1095 pResult->setName(uDef.getName());
1096 pResult->setId(uDef.getId());
1097 maxUnits = pResult->getNumUnits();
1098 counter = 1;
1099 if (maxUnits > 0)
1100 {
1101 Unit* pFirst = pResult->getUnit(0);
1102 while (counter < maxUnits)
1103 {
1104 Unit* pU = pResult->getUnit(counter);
1105 int scale = pU->getScale();
1106 if (scale != 0)
1107 {
1108 pFirst->setScale(scale + pFirst->getScale());
1109 }
1110 double multiplier = pU->getMultiplier();
1111 if (multiplier != 1.0)
1112 {
1113 // if the multiplier is 0, the unit definition does not make sense
1114 // we treat this as an error rather than returning a dimensionless
1115 // UnitDefinition
1116 if (multiplier == 0.0)
1117 {
1118 delete pResult;
1119 pResult = NULL;
1120 break;
1121 }
1122 pFirst->setMultiplier(multiplier*pFirst->getMultiplier());
1123 }
1124 ++counter;
1125 }
1126 }
1127 }
1128 return pResult;
1129 }
1130  */
1131 
1132 /*
1133  * Combines two UnitDefinitions by combining the equivalent units from
1134  * both UnitDefinitions.
1135  * A new UnitDefinition containing the combination is returned.
1136  * If two eqivalent units have a different offset, the function returns a
1137  * NULL pointer.
1138  * It is up to the receiver to free the memory of the returned UnitDefinition.
1139  * @param const UnitDefinition& uDef1
1140  * @param const UnitDefinition& uDef2
1141  * @return UnitDefinition* result
1142  */
1143 LIBSBML_EXTERN
1144 UnitDefinition* UnitConversionFactory::combine(const UnitDefinition& uDef1, const UnitDefinition& uDef2)
1145 {
1146  // take all Units from the first UnitDefinition make copies and put them into the new UnitDefinition
1147  // go through all Units in the second UnitDefinition, if the same unit already exists in the new
1148  // UnitDefinition combine them, else add a copy of the Unit to the new UnitDefinition
1149  UnitDefinition* pResult = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1150  unsigned int maxUnits = uDef1.getNumUnits();
1151  unsigned int i;
1152 
1153  for (i = 0; i < maxUnits; ++i)
1154  {
1155  const Unit* pSrcUnit = uDef1.getUnit(i);
1156  unsigned int maxUnits2 = pResult->getNumUnits();
1157  unsigned int j;
1158  bool exists = false;
1159 
1160  for (j = 0; j < maxUnits2; ++j)
1161  {
1162  Unit* pResultUnit = pResult->getUnit(j);
1163 
1164  if (pResultUnit->getKind() == pSrcUnit->getKind())
1165  {
1166  exists = true;
1167 
1168  // if the offsets are different, we can not combine the units
1169  if (pResultUnit->getOffset() != pSrcUnit->getOffset())
1170  {
1171  delete pResult;
1172  return NULL;
1173  }
1174 
1175  pResultUnit->setMultiplier(pResultUnit->getMultiplier()*pSrcUnit->getMultiplier()*pow(10.0, pResultUnit->getScale() - pSrcUnit->getScale()));
1176  pResultUnit->setExponent(pResultUnit->getExponent() + pSrcUnit->getExponent());
1177 
1178  // if the resulting scale is 0, the units have canceled each other out
1179  // and we set the kind to dimensionless so that it can be eliminated
1180  // later on
1181  if (pResultUnit->getExponent() == 0)
1182  {
1183  pResultUnit->setKind(UNIT_KIND_DIMENSIONLESS);
1184  }
1185  }
1186  }
1187 
1188  if (!exists)
1189  {
1190  Unit* tmpUnit = new Unit(*pSrcUnit);
1191  pResult->addUnit(tmpUnit);
1192  delete tmpUnit;
1193  }
1194  }
1195 
1196  maxUnits = uDef2.getNumUnits();
1197 
1198  for (i = 0; i < maxUnits; ++i)
1199  {
1200  const Unit* pSrcUnit = uDef2.getUnit(i);
1201  unsigned int maxUnits2 = pResult->getNumUnits();
1202  unsigned int j;
1203  bool exists = false;
1204 
1205  for (j = 0; j < maxUnits2; ++j)
1206  {
1207  Unit* pResultUnit = pResult->getUnit(j);
1208 
1209  if (pResultUnit->getKind() == pSrcUnit->getKind())
1210  {
1211  exists = true;
1212 
1213  // if the offsets are different, we can not combine the units
1214  if (pResultUnit->getOffset() != pSrcUnit->getOffset())
1215  {
1216  delete pResult;
1217  return NULL;
1218  }
1219 
1220  pResultUnit->setMultiplier(pResultUnit->getMultiplier()*pSrcUnit->getMultiplier()*pow(10.0, pResultUnit->getScale() - pSrcUnit->getScale()));
1221  pResultUnit->setExponent(pResultUnit->getExponent() + pSrcUnit->getExponent());
1222 
1223  // if the resulting scale is 0, the units have canceled each other out
1224  // and we set the kind to dimensionless so that it can be eliminated
1225  // later on
1226  if (pResultUnit->getExponent() == 0)
1227  {
1228  pResultUnit->setKind(UNIT_KIND_DIMENSIONLESS);
1229  }
1230  }
1231  }
1232 
1233  if (!exists)
1234  {
1235  Unit* tmpUnit = new Unit(*pSrcUnit);
1236  pResult->addUnit(tmpUnit);
1237  delete tmpUnit;
1238  }
1239  }
1240 
1241  UnitDefinition* pTmp = UnitConversionFactory::eliminateDimensionless(pResult);
1242 
1243  if (pTmp)
1244  {
1245  delete pResult;
1246  pResult = pTmp;
1247  }
1248 
1249  return pResult;
1250 }
1251 
1252 /*
1253  * Eliminate all dimensionless units from the given UnitDefinition.
1254  * A new UnitDefinition without the dimensionless units is returned.
1255  * The scale and multiplier are preserved. If the UnitDefinition has only
1256  * one unit the is a dimensionless, it is not deleted.
1257  * @param UnitDefinition* pUdef
1258  * @return UnitDefinition* result
1259  */
1260 LIBSBML_EXTERN
1261 UnitDefinition* UnitConversionFactory::eliminateDimensionless(UnitDefinition* pUdef)
1262 {
1263  unsigned int maxUnits = pUdef->getNumUnits();
1264  UnitDefinition* pTmpUdef = NULL;
1265  Unit* pU = NULL;
1266 
1267  if (maxUnits > 1)
1268  {
1269  int scale = 0;
1270  double multiplier = 1.0;
1271  unsigned int i = 0;
1272  pTmpUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION);
1273 
1274  while (i < maxUnits)
1275  {
1276  pU = new Unit(*(pUdef->getUnit(i)));
1277 
1278  if (pU->getKind() != UNIT_KIND_DIMENSIONLESS)
1279  {
1280  pTmpUdef->addUnit(pU);
1281  }
1282  else
1283  {
1284  // conserve scale and multiplier
1285  scale = scale + pU->getScale();
1286  multiplier = multiplier * pU->getMultiplier();
1287  }
1288 
1289  delete pU;
1290  ++i;
1291  }
1292 
1293  i = pTmpUdef->getNumUnits();
1294 
1295  if (i > 0 && i < maxUnits)
1296  {
1297  pTmpUdef->setName(pUdef->getName());
1298  pTmpUdef->setId(pUdef->getId());
1299  pU = pTmpUdef->getUnit(0);
1300  pU->setScale(pU->getScale() + scale);
1301  pU->setMultiplier(pU->getMultiplier()*multiplier);
1302  }
1303  else
1304  {
1305  delete pTmpUdef;
1306  pTmpUdef = NULL;
1307  }
1308  }
1309 
1310  return pTmpUdef;
1311 }
1312 
1313 /*
1314  * Converts a UnitDefinition into the corresponding UnitDefinition that consists
1315  * only of SI units.
1316  * Possible offsets are ignored.
1317  * Freeing the memory for the returned UnitDefinition is up to the
1318  * receiver.
1319  * On failure a NULL pointer is returned.
1320  * @param const UnitDefinition& uDef
1321  * @return UnitDefinition* result
1322  */
1323 LIBSBML_EXTERN
1324 UnitDefinition* UnitConversionFactory::convertToSI(const UnitDefinition& uDef)
1325 {
1326  // convert all contained units to SI units
1327  // combine the resulting unitdefinitions
1328  UnitDefinition* pResult = NULL;
1329  UnitDefinition* pTmpDef = NULL;
1330  unsigned int i;
1331  unsigned int maxUnits = uDef.getNumUnits();
1332 
1333  if (maxUnits > 0)
1334  {
1335  pTmpDef = UnitConversionFactory::convertToSI(*(uDef.getUnit(0)));
1336  pResult = pTmpDef;
1337 
1338  for (i = 1; i < maxUnits; ++i)
1339  {
1340  UnitDefinition* pTmpDef2 = UnitConversionFactory::convertToSI(*(uDef.getUnit(i)));
1341  pResult = UnitConversionFactory::combine(*pTmpDef, *pTmpDef2);
1342  delete pTmpDef;
1343  delete pTmpDef2;
1344 
1345  // stop if the result was a NULL pointer
1346  if (!pResult) break;
1347 
1348  pTmpDef = pResult;
1349  }
1350  }
1351 
1352  return pResult;
1353 }
1354 
1355 /*
1356  * Checks if two UnitDefinitions are equivalent, i.e. wether they are
1357  * interconvertible.
1358  * This is the case if they consist of the same set of units
1359  * with the same exponents after being
1360  * converted to SI units. The scales of the equivalent units may differ.
1361  * If the offset of two equivalent units differ, false is returned.
1362  * @param const UnitDefinition& uDef1
1363  * @param const UnitDefinition& uDef2
1364  * @return bool areEquivalent
1365  */
1366 LIBSBML_EXTERN
1367 bool UnitConversionFactory::areEquivalent(const UnitDefinition& uDef1, const UnitDefinition& uDef2)
1368 {
1369  bool equivalent = true;
1370  UnitDefinition* pTmpUdef1 = UnitConversionFactory::convertToSI(uDef1);
1371  UnitDefinition* pTmpUdef2 = UnitConversionFactory::convertToSI(uDef2);
1372 
1373  if (pTmpUdef1 && pTmpUdef2)
1374  {
1375  unsigned int maxUnits = pTmpUdef1->getNumUnits();
1376 
1377  if (maxUnits == pTmpUdef2->getNumUnits())
1378  {
1379  unsigned int i;
1380 
1381  // for all units the UnitKind and the exponent must be the same for the unit
1382  // definitions to be interconvertible
1383  for (i = 0; i < maxUnits; ++i)
1384  {
1385  Unit* pUnit1 = pTmpUdef1->getUnit(i);
1386  Unit* pUnit2 = pTmpUdef2->getUnit(i);
1387 
1388  if (pUnit1->getKind() != pUnit2->getKind())
1389  {
1390  equivalent = false;
1391  break;
1392  }
1393 
1394  if (pUnit1->getExponent() != pUnit2->getExponent())
1395  {
1396  equivalent = false;
1397  break;
1398  }
1399  }
1400  }
1401  else
1402  {
1403  equivalent = false;
1404  }
1405 
1406  delete pTmpUdef1;
1407  delete pTmpUdef2;
1408  }
1409  else
1410  {
1411  equivalent = false;
1412  }
1413 
1414  return equivalent;
1415 }
1416 
1417 /*
1418  * Checks if two UnitDefinitions are equal.
1419  * This is the case if they consist of the same set of units with the same scale and exponent
1420  * after being converted to SI units.
1421  * If the offset of two equivalent units differ, false is returned.
1422  * @param const UnitDefinition& uDef1
1423  * @param const UnitDefinition& uDef2
1424  * @return bool areEqual
1425  */
1426 LIBSBML_EXTERN
1427 bool UnitConversionFactory::areEqual(const UnitDefinition& uDef1, const UnitDefinition& uDef2)
1428 {
1429  bool equal = true;
1430  UnitDefinition* pTmpUdef1 = UnitConversionFactory::convertToSI(uDef1);
1431  UnitDefinition* pTmpUdef2 = UnitConversionFactory::convertToSI(uDef2);
1432 
1433  if (pTmpUdef1 && pTmpUdef2)
1434  {
1435  unsigned int maxUnits = pTmpUdef1->getNumUnits();
1436 
1437  if (maxUnits == pTmpUdef2->getNumUnits())
1438  {
1439  unsigned int i;
1440 
1441  // for all units the UnitKind and the exponent must be the same for the unit
1442  // definitions to be interconvertible
1443  for (i = 0; i < maxUnits; ++i)
1444  {
1445  Unit* pUnit1 = pTmpUdef1->getUnit(i);
1446  Unit* pUnit2 = pTmpUdef2->getUnit(i);
1447 
1448  if (pUnit1->getKind() != pUnit2->getKind())
1449  {
1450  equal = false;
1451  break;
1452  }
1453 
1454  if (pUnit1->getExponent() != pUnit2->getExponent())
1455  {
1456  equal = false;
1457  break;
1458  }
1459 
1460  if (pUnit1->getScale() != pUnit2->getScale())
1461  {
1462  equal = false;
1463  break;
1464  }
1465  }
1466  }
1467  else
1468  {
1469  equal = false;
1470  }
1471 
1472  delete pTmpUdef1;
1473  delete pTmpUdef2;
1474  }
1475  else
1476  {
1477  equal = false;
1478  }
1479 
1480  return equal;
1481 }
1482 
1483 /*
1484  * Converts the given value from the given source UnitDefinition to the
1485  * given destination UnitDefinition if the two UnitDefinitions are
1486  * equivalent.
1487  * The original value is changed. On success the functions returns true,
1488  * otherwise it returns false.
1489  * @param const double* value
1490  * @param const UnitDefinition& srcUdef
1491  * @param const UnitDefinition& destUdef
1492  * @return bool success
1493  */
1494 LIBSBML_EXTERN
1495 bool UnitConversionFactory::convertValue(double *value, const UnitDefinition& srcUdef, const UnitDefinition& destUdef)
1496 {
1497  bool success = true;
1498 
1499  if (UnitConversionFactory::areEquivalent(srcUdef, destUdef))
1500  {
1501  UnitDefinition* pTmpUdef1 = UnitConversionFactory::convertToSI(srcUdef);
1502  UnitDefinition* pTmpUdef2 = UnitConversionFactory::convertToSI(destUdef);
1503  // both UnitDefinitions should only differ in the multiplier of the first unit
1504  double factor = pTmpUdef1->getUnit(0)->getMultiplier() / pTmpUdef2->getUnit(0)->getMultiplier();
1505  int scaleDiff = pTmpUdef1->getUnit(0)->getScale() - pTmpUdef2->getUnit(0)->getScale();
1506  factor = factor * pow(10.0, scaleDiff);
1507  *value = (*value) * factor;
1508  delete pTmpUdef1;
1509  delete pTmpUdef2;
1510  }
1511  else
1512  {
1513  success = false;
1514  }
1515 
1516  return success;
1517 }
1518 
1519 /*
1520  * The functions determins wether the given UnitDefinition contains only
1521  * units from the list given as the second argument.
1522  * @param const UnitDefinition& uDef
1523  * @param const ListOf& unitList
1524  * @return bool containsOnlyGivenUnits
1525  */
1526 LIBSBML_EXTERN
1527 bool UnitConversionFactory::containsOnlyGivenUnits(const UnitDefinition& uDef, const ListOf& unitList)
1528 {
1529  bool result = true;
1530  UnitDefinition* pTmpUdef = UnitConversionFactory::convertToSI(uDef);
1531 
1532  if (pTmpUdef)
1533  {
1534  unsigned int i;
1535  unsigned int maxUnits = pTmpUdef->getNumUnits();
1536 
1537  for (i = 0; i < maxUnits; ++i)
1538  {
1539  Unit* pU = pTmpUdef->getUnit(i);
1540  UnitKind_t kind = pU->getKind();
1541  unsigned int j;
1542  unsigned int maxUnits2 = unitList.size();
1543  bool found = false;
1544 
1545  for (j = 0; j < maxUnits2; ++j)
1546  {
1547  const Unit* pU2 = dynamic_cast<const Unit*>(unitList.get(j));
1548 
1549  if (!pU2) break;
1550 
1551  if (pU2->getKind() == kind)
1552  {
1553  found = true;
1554  break;
1555  }
1556  }
1557 
1558  if (!found)
1559  {
1560  result = false;
1561  break;
1562  }
1563  }
1564 
1565  delete pTmpUdef;
1566  }
1567  else
1568  {
1569  result = false;
1570  }
1571 
1572  return result;
1573 }
1574 
1575 /*
1576  * Checks wether a given id is has already been used by the conversion
1577  * framework.
1578  * @param const std::string id
1579  * @return bool isUnused
1580  */
1581 LIBSBML_EXTERN
1582 bool UnitConversionFactory::isIdUnused(const std::string& id)
1583 {
1584  bool unused = true;
1585  size_t i;
1586  size_t maxIds = usedIds.size();
1587 
1588  for (i = 0; i < maxIds; ++i)
1589  {
1590  if (id == usedIds[i])
1591  {
1592  unused = false;
1593  break;
1594  }
1595  }
1596 
1597  return unused;
1598 }
1599 
1600 /*
1601  * Returns a string representation of the given Unit. THis function is
1602  * only for debugging purposes.
1603  * @param const UnitDefinition& uDef
1604  * @return std::string unitDefinitionRepresentation
1605  */
1606 LIBSBML_EXTERN
1607 std::string UnitConversionFactory::toString(const UnitDefinition& uDef)
1608 {
1609  unsigned int maxUnits = uDef.getNumUnits();
1610  unsigned int i;
1611  std::stringstream ss;
1612 
1613  for (i = 0; i < maxUnits; ++i)
1614  {
1615  ss << "(" << UnitConversionFactory::toString(*(uDef.getUnit(i))) << ") ";
1616  }
1617 
1618  return ss.str();
1619 }
1620 
1621 /*
1622  * Returns a string representation of the given Unit. THis function is
1623  * only for debugging purposes.
1624  * @param const Unit& unit
1625  * @return std::string unitRepresentation
1626  */
1627 LIBSBML_EXTERN
1628 std::string UnitConversionFactory::toString(const Unit& unit)
1629 {
1630  double multiplier = unit.getMultiplier();
1631  double offset = unit.getOffset();
1632  int scale = unit.getScale();
1633  int exponent = unit.getExponent();
1634  UnitKind_t kind = unit.getKind();
1635  std::stringstream ss;
1636  ss << multiplier << " * (" << UnitKind_toString(kind) << " * 10^" << scale << " + " << offset << ")^" << exponent;
1637  return ss.str();
1638 }
1639 
1640 /**
1641  * Returns the SBML level that is passed to constructors of unit definitions.
1642  */
1643 unsigned int UnitConversionFactory::getSBMLLevel()
1644 {
1645  return SBML_LEVEL;
1646 }
1647 
1648 /**
1649  * Returns the SBML version that is passed to constructors of unit definitions.
1650  */
1651 unsigned int UnitConversionFactory::getSBMLVersion()
1652 {
1653  return SBML_VERSION;
1654 }
1655 
1656 /**
1657  * Changes the SBML level that is passed to constructors of unit definitions.
1658  */
1659 void UnitConversionFactory::setSBMLLevel(unsigned int level)
1660 {
1661  SBML_LEVEL = level;
1662 }
1663 
1664 /**
1665  * Changes the SBML version that is passed to constructors of unit definitions.
1666  */
1667 void UnitConversionFactory::setSBMLVersion(unsigned int version)
1668 {
1669  SBML_VERSION = version;
1670 }
const CArrayAnnotation * pResult