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

Last change on this file since 73 was 73, checked in by dkearney, 15 years ago
  1. changes to RpUnits, modified RpUnits::define() function not to look for base units.
  2. changed python RpUnits to return string when units!="off" and a number when units=="off"
  3. modified make files, hopefully making them easier to read, removing vpaths,

cleaning up the make process, combining smaller libraries into one library,
librappture, and putting the core objects into one library - libRpObjects,
for testing.

  1. copied rpResult function into rappture_interface.c to stop compiler from

complaining about undefined references ot the function. trying to use the
function probably won't work. but that can be fixed after the repository is
reorganized.

  1. in example/app-fermi/python/fermi.py, changed exit() to sys.exit() to

stop python from complaining about no function called exit().

  1. examples/app-fermi/fortran still does not run, but new rappture parser

should take care of these problems. (same with examples/fermi_fortran)

  • Property svn:executable set to *
File size: 14.8 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    private:
325
326        // i hope to replace these vars with a small class representing a
327        // of a linked list of units. that way we can handle complex units.
328        // this will also require that we move the getUnits, getExponent,
329        // and getBasis, makeBasis functionality into the smaller class,
330        // that represents each part of the units. we should keep getUnits,
331        // getBasis, and makeBasis in this class, but modify them to go
332        // through the linked list of units and combine the units back into
333        // what the caller expects to see.
334        // ie. cm2/Vms (mobility), will be split into the objects cm2, V, ms
335        // when getUnits is called, the user should see cm2/Vms again.
336        // for basis, possibly let the user choose a basis, and for makeBasis
337        // move through the linked list, only converting the metric elements.
338        //
339       
340        // used by the RpUnits when defining units elements
341        unit* head;
342
343        // linked list of units this RpUnit can convert to
344        convEntry* convList;
345
346        // used by the RpUnits when defining conversion elements
347        conversion* conv;
348
349        // dictionary to store the units.
350        // dict pointer
351        // static RpDict<std::string,RpUnits*> dict;
352        static RpDict<std::string,RpUnits*>* dict;
353
354        // create a units element
355        // class takes in three pieces of info
356        // 1) string describing the units
357        // 2) double describing the exponent
358        // 3) pointer to RpUnits object describing the basis
359        //      of the units (the fundamental unit)
360        //
361        RpUnits (
362                    const std::string& units,
363                    double& exponent,
364                    // RpUnits* basis[]
365                    RpUnits* basis
366                )
367            :   head        ( new unit( units, exponent, basis, NULL) ),
368                convList    (NULL),
369                conv        (NULL)
370        {};
371
372        // create a conversion element
373
374        RpUnits (
375                    RpUnits* from,
376                    RpUnits* to,
377                    double (*convForwFxnPtr)(double),
378                    double (*convBackFxnPtr)(double),
379                    conversion* prev,
380                    conversion* next
381                )
382            :   head (NULL),
383                convList (NULL),
384                conv (new conversion
385                        (from,to,convForwFxnPtr,convBackFxnPtr,prev,next))
386        {
387            connectConversion(from);
388            connectConversion(to);
389        };
390
391        RpUnits (
392                    RpUnits* from,
393                    RpUnits* to,
394                    void* (*convForwFxnPtr)(void*, void*),
395                    void* convForwData,
396                    void* (*convBackFxnPtr)(void*, void*),
397                    void* convBackData,
398                    conversion* prev,
399                    conversion* next
400                )
401            :   head (NULL),
402                convList (NULL),
403                conv (new conversion (  from, to,
404                                        convForwFxnPtr, convForwData,
405                                        convBackFxnPtr, convBackData,
406                                        prev, next
407                                     )
408                     )
409        {
410            connectConversion(from);
411            connectConversion(to);
412        };
413
414        // default destructor
415        //
416        //~RpUnits ();
417        ~RpUnits ()
418        {
419            // clean up dynamic memory
420
421            unit* p = head;
422            while (p != NULL) {
423                unit* tmp = p;
424                p = p->next;
425                delete tmp;
426            }
427        }
428
429        void RpUnits::connectConversion(RpUnits* myRpUnit);
430
431        void RpUnits::fillMetricMap();
432
433        // create the container keeping track of defined units
434        // returns 0 on success (table created or already exists)
435        // returns !0 on failure (table not created or cannot exist)
436        int RpUnits::createUnitsTable();
437
438        // insert new RpUnits object into RpUnitsTable
439        // returns 0 on success (object inserted or already exists)
440        // returns !0 on failure (object cannot be inserted or dne)
441        int RpUnits::insert(std::string key);   
442
443        // link two RpUnits objects that already exist in RpUnitsTable
444        // returns 0 on success (linking within table was successful)
445        // returns !0 on failure (linking was not successful)
446        int RpUnits::link(RpUnits * unitA);
447
448
449        static int pre_compare( std::string& units, RpUnits* basis = NULL);
450        void addUnit( const std::string& units,
451                      double &  exponent,
452                      RpUnits * basis
453                     );
454
455        static int addPresetAll();
456        static int addPresetEnergy();
457        static int addPresetLength();
458        static int addPresetTemp();
459        static int addPresetTime();
460
461
462};
463
464/*--------------------------------------------------------------------------*/
465/*--------------------------------------------------------------------------*/
466
467// #include "../src/RpUnits.cc"
468
469#endif
Note: See TracBrowser for help on using the repository browser.