source: trunk/include/core/RpUnits.h @ 76

Last change on this file since 76 was 76, checked in by dkearney, 15 years ago
  1. cleaned up make files some more, deleted make.inc files
  2. updated RpUnits module and Cee and Fortran interfaces
  3. changed return values for some fortran interfaces,

error messages not working yet

  1. still need to add copy assignment code to RpUnits
  • Property svn:executable set to *
File size: 15.0 KB
Line 
1#include <iostream>
2#include <string>
3#include <sstream>
4#include <stdlib.h>
5#include <errno.h>
6
7#ifndef _RpDICT_H
8    #include "RpDict.h"
9#endif
10
11#include "RpUnitsStd.h"
12
13#ifndef _RpUNITS_H
14#define _RpUNITS_H
15
16class RpUnits;
17
18class unit
19{
20
21    public:
22
23        const std::string getUnits(){ return units; };
24        double getExponent() {return exponent;};
25        RpUnits * getBasis() {return basis;};
26
27        friend class RpUnits;
28
29    private:
30        const std::string units;
31        double exponent;
32        // RpUnits* basis[4];
33        RpUnits* basis;
34
35        unit* prev;
36        unit* next;
37
38        unit (
39                const std::string& units,
40                double&            exponent,
41                // RpUnits**           basis,
42                RpUnits*           basis,
43                unit*              next
44             )
45            :   units    (units),
46                exponent (exponent),
47                basis    (basis),
48                prev     (NULL),
49                next     (next)
50            { };
51
52
53        void newExponent(double newExponent) {exponent = newExponent;};
54
55
56};
57
58// simple class to hold info about a conversion.
59// holds where we are converting from
60// holds where we are converting to
61// hold the pointer to a function to do the forward conversion (from->to)
62// hold the pointer to a function to do the backward conversion (to->from)
63//
64class conversion
65{
66    public:
67
68        const RpUnits* getFrom()    { return (const RpUnits*) fromPtr; };
69        const RpUnits* getTo()      { return (const RpUnits*) toPtr; };
70       
71        friend class RpUnits;
72
73    private:
74
75        RpUnits* fromPtr;
76        RpUnits* toPtr;
77        double (*convForwFxnPtr)(double);
78        double (*convBackFxnPtr)(double);
79        void* (*convForwFxnPtrVoid)(void*, void*);
80        void* convForwData;
81        void* (*convBackFxnPtrVoid)(void*, void*);
82        void* convBackData;
83
84        conversion* prev;
85        conversion* next;
86
87        // constructor
88        // private because i only want RpUnits to be able to
89        // create a conversion
90        conversion (
91                RpUnits* fromPtr,
92                RpUnits* toPtr,
93                double (*convForwFxnPtr)(double),
94                double (*convBackFxnPtr)(double),
95                conversion* prev,
96                conversion* next
97             )
98            :   fromPtr             (fromPtr),
99                toPtr               (toPtr),
100                convForwFxnPtr      (convForwFxnPtr),
101                convBackFxnPtr      (convBackFxnPtr),
102                convForwFxnPtrVoid  (NULL),
103                convForwData        (NULL),
104                convBackFxnPtrVoid  (NULL),
105                convBackData        (NULL),
106                prev                (prev),
107                next                (next)
108            {
109            };
110
111        conversion (
112                RpUnits* fromPtr,
113                RpUnits* toPtr,
114                void* (*convForwFxnPtrVoid)(void*, void*),
115                void* convForwData,
116                void* (*convBackFxnPtrVoid)(void*, void*),
117                void* convBackData,
118                conversion* prev,
119                conversion* next
120             )
121            :   fromPtr             (fromPtr),
122                toPtr               (toPtr),
123                convForwFxnPtr      (NULL),
124                convBackFxnPtr      (NULL),
125                convForwFxnPtrVoid  (convForwFxnPtrVoid),
126                convForwData        (convForwData),
127                convBackFxnPtrVoid  (convBackFxnPtrVoid),
128                convBackData        (convBackData),
129                prev                (prev),
130                next                (next)
131            {
132            };
133
134        // copy constructor
135
136        // destructor
137};
138
139// used by the RpUnits class to create a linked list of the conversions
140// associated with the specific unit.
141//
142// we could templitize this and make a generic linked list
143// or could use generic linked list class from book programming with objects
144//
145class convEntry
146{
147
148    public:
149
150        friend class RpUnits;
151
152    private:
153
154        conversion* conv;
155        convEntry*  prev;
156        convEntry*  next;
157
158        convEntry (
159                conversion* conv,
160                convEntry*  prev,
161                convEntry*  next
162             )
163            :   conv    (conv),
164                prev    (prev),
165                next    (next)
166            { };
167
168        /*
169        ~convEntry()
170        {
171
172        }
173        */
174};
175
176class RpUnits
177{
178    /*
179     * helpful units site
180     * http://aurora.regenstrief.org/~gunther/units.html
181     */
182
183    public:
184       
185        // users member fxns
186        std::string getUnits();
187        std::string getUnitsName();
188        double getExponent();
189        RpUnits* getBasis();
190
191        // convert from one RpUnits to another if the conversion is defined
192        double convert(RpUnits* toUnits, double val, int* result = NULL);
193        // convert from one RpUnits to another if the conversion is defined
194        void* convert(RpUnits* toUnits, void* val, int* result = NULL);
195        // convert from one RpUnits to another if the conversion is defined
196        double convert(std::string, double val);
197        // convert from one RpUnits to another if the conversion is defined
198        std::string convert (   RpUnits* toUnits,
199                                double val,
200                                int showUnits = 0,
201                                int* result = NULL  );
202
203        static std::string convert ( std::string val,
204                                     std::string toUnits,
205                                     int showUnits,
206                                     int* result = NULL );
207
208        // dictionary to store the units.
209        // static RpDict<std::string,RpUnits> dict;
210
211        // turn the current unit to the metric system
212        // this should only be used for units that are part of the
213        // metric system. doesnt deal with exponents, just prefixes
214        double makeBasis(double value, int* result = NULL);
215        RpUnits & makeBasis(double* value, int* result = NULL);
216       
217        static int makeMetric(RpUnits * basis);
218
219        // find a RpUnits object that should exist in RpUnitsTable
220        // returns 0 on success (object was found)
221        // returns !0 on failure (object not found)
222        static RpUnits* find(std::string key)
223        {
224            // dict.find seems to return a (RpUnits* const) so i had to
225            // cast it as a (RpUnits*)
226
227            // dict pointer
228             // RpUnits* unitEntry = (RpUnits*) *(dict.find(key).getValue());
229             RpUnits* unitEntry = (RpUnits*) *(dict->find(key).getValue());
230
231            // RpUnits* unitEntry = (RpUnits*) dEntr.getValue();
232
233            // dict pointer
234            // if (unitEntry == (RpUnits*)dict.getNullEntry().getValue()) {
235            if (unitEntry == (RpUnits*)dict->getNullEntry().getValue()) {
236                unitEntry = NULL;
237            }
238
239            return unitEntry;
240        };
241
242        // user calls define to add a RpUnits object or to add a relation rule
243        //
244        // add RpUnits Object
245        static RpUnits * define(const std::string units, RpUnits * basis);
246        static RpUnits * defineCmplx(const std::string units,RpUnits * basis);
247        //
248        // add relation rule
249
250        static RpUnits * define(RpUnits* from,
251                                RpUnits* to,
252                                double (*convForwFxnPtr)(double),
253                                double (*convBackFxnPtr)(double));
254
255        static RpUnits * define(RpUnits* from,
256                                RpUnits* to,
257                                void* (*convForwFxnPtr)(void*, void*),
258                                void* convForwData,
259                                void* (*convBackFxnPtr)(void*, void*),
260                                void* convBackData);
261
262        // populate the dictionary with a set of units specified by group
263        // if group equals......................then load................
264        //      "all"                       load all available units
265        //      "energy"                    load units related to length
266        //      "length"                    load units related to length
267        //      "temp"                      load units related to temperature
268        //      "time"                      load units related to time
269        //  (no other groups have been created)
270
271        static int addPresets (std::string group);
272
273        // undefining a relation rule is probably not needed
274        // int undefine(); // delete a relation
275
276        // convert fxn will be taken care of in the RpUnitsConversion class
277        // i think
278        // int convert(const char* from, const char* to);
279
280        // why are these functions friends...
281        // probably need to find a better way to let RpUnits
282        // use the RpDict and RpDictEntry fxns
283        friend class RpDict<std::string,RpUnits*>;
284        friend class RpDictEntry<std::string,RpUnits*>;
285
286        // copy constructor
287        RpUnits ( const RpUnits& myRpUnit )
288        {
289
290            /*
291            from = myRpUnit.from;
292            to = myRpUnit.to;
293            convertForw = myRpUnit.convertForw;
294            convertBack = myRpUnit.convertBack;
295            */
296
297            // copy constructor for unit
298            unit* tmp = NULL;
299            unit* newUnit = NULL;
300            unit* p = myRpUnit.head;
301
302            while (p != NULL) {
303                newUnit = new unit(p->units, p->exponent,p->basis,NULL);
304
305                newUnit->prev = tmp;
306                if (tmp) {
307                    tmp->next = newUnit;
308                }
309
310                tmp = newUnit;
311                p = p->next;
312            }
313
314            if (tmp) {
315                while (tmp->prev != NULL) {
316                   tmp = tmp->prev;
317                }
318            }
319
320            head = tmp;
321               
322        };
323       
324        /*
325        RpUnits& operator= (const RpUnits& myRpUnit) {
326
327            if ( this != &myRpUnit ) {
328                delete head;
329                delete convList;
330                delete conv;
331            }
332        }
333        */
334       
335    private:
336
337        // i hope to replace these vars with a small class representing a
338        // of a linked list of units. that way we can handle complex units.
339        // this will also require that we move the getUnits, getExponent,
340        // and getBasis, makeBasis functionality into the smaller class,
341        // that represents each part of the units. we should keep getUnits,
342        // getBasis, and makeBasis in this class, but modify them to go
343        // through the linked list of units and combine the units back into
344        // what the caller expects to see.
345        // ie. cm2/Vms (mobility), will be split into the objects cm2, V, ms
346        // when getUnits is called, the user should see cm2/Vms again.
347        // for basis, possibly let the user choose a basis, and for makeBasis
348        // move through the linked list, only converting the metric elements.
349        //
350       
351        // used by the RpUnits when defining units elements
352        unit* head;
353
354        // linked list of units this RpUnit can convert to
355        convEntry* convList;
356
357        // used by the RpUnits when defining conversion elements
358        conversion* conv;
359
360        // dictionary to store the units.
361        static RpDict<std::string,RpUnits*>* dict;
362
363        // create a units element
364        // class takes in three pieces of info
365        // 1) string describing the units
366        // 2) double describing the exponent
367        // 3) pointer to RpUnits object describing the basis
368        //      of the units (the fundamental unit)
369        //
370
371
372
373        RpUnits (
374                    const std::string& units,
375                    double& exponent,
376                    // RpUnits* basis[]
377                    RpUnits* basis
378                )
379            :   head        ( new unit( units, exponent, basis, NULL) ),
380                convList    (NULL),
381                conv        (NULL)
382        {};
383
384        // create a conversion element
385
386
387
388       
389        RpUnits (
390                    RpUnits* from,
391                    RpUnits* to,
392                    double (*convForwFxnPtr)(double),
393                    double (*convBackFxnPtr)(double),
394                    conversion* prev,
395                    conversion* next
396                )
397            :   head (NULL),
398                convList (NULL),
399                conv (new conversion
400                        (from,to,convForwFxnPtr,convBackFxnPtr,prev,next))
401        {
402            connectConversion(from);
403            connectConversion(to);
404        };
405
406
407
408
409       
410        RpUnits (
411                    RpUnits* from,
412                    RpUnits* to,
413                    void* (*convForwFxnPtr)(void*, void*),
414                    void* convForwData,
415                    void* (*convBackFxnPtr)(void*, void*),
416                    void* convBackData,
417                    conversion* prev,
418                    conversion* next
419                )
420            :   head (NULL),
421                convList (NULL),
422                conv (new conversion (  from, to,
423                                        convForwFxnPtr, convForwData,
424                                        convBackFxnPtr, convBackData,
425                                        prev, next
426                                     )
427                     )
428        {
429            connectConversion(from);
430            connectConversion(to);
431        };
432
433        // default destructor
434        //
435        ~RpUnits ()
436        {
437            // clean up dynamic memory
438
439            unit* p = head;
440            while (p != NULL) {
441                unit* tmp = p;
442                p = p->next;
443                delete tmp;
444            }
445        }
446
447        void RpUnits::connectConversion(RpUnits* myRpUnit);
448
449        void RpUnits::fillMetricMap();
450
451        // create the container keeping track of defined units
452        // returns 0 on success (table created or already exists)
453        // returns !0 on failure (table not created or cannot exist)
454        int RpUnits::createUnitsTable();
455
456        // insert new RpUnits object into RpUnitsTable
457        // returns 0 on success (object inserted or already exists)
458        // returns !0 on failure (object cannot be inserted or dne)
459        int RpUnits::insert(std::string key);   
460
461        // link two RpUnits objects that already exist in RpUnitsTable
462        // returns 0 on success (linking within table was successful)
463        // returns !0 on failure (linking was not successful)
464        int RpUnits::link(RpUnits * unitA);
465
466
467        static int pre_compare( std::string& units, RpUnits* basis = NULL);
468        void addUnit( const std::string& units,
469                      double &  exponent,
470                      RpUnits * basis
471                     );
472
473        static int addPresetAll();
474        static int addPresetEnergy();
475        static int addPresetLength();
476        static int addPresetTemp();
477        static int addPresetTime();
478
479
480};
481
482/*--------------------------------------------------------------------------*/
483/*--------------------------------------------------------------------------*/
484
485// #include "../src/RpUnits.cc"
486
487#endif
Note: See TracBrowser for help on using the repository browser.