Changeset 568 for trunk/src/core


Ignore:
Timestamp:
Jan 23, 2007 10:15:07 PM (17 years ago)
Author:
dkearney
Message:

reworking of the Rappture Units code.
Rappture Units no longer creates an object for each metric extension of every
metric unit. Now the metric prefixes are kept in the dictionary as unit objects,
and when a unit is parsed out of the string received from the user, the unit
is checked to see if it acccepts metric prefixes, if so, a search is done for
the prefix. This allows Rappture Units code to more easily tackle case insensitive
unit name searches. Eventually the prefixes will be removed as direct Rappture Units objects and be turned into (possibly a derived object) rappture units prefix objects.

The find function of the core Rappture Units code now accepts
a "hints" function pointer. The function pointer is executed by the dictionary when
the dictionary thinks it found a matching object. This allows the user of the
dictionary to insert different objects with the same key. For Rappture Units,
multiple units objects with the same key can be inserted into the dictionary.
This is important for units like "A" which could stand for angstroms or amperes.

Additionally, the "make metric" functions were removed because the idea of being a
metric unit has been reduced to a flag inside the Rappture Units object and some
newly added logic. The role of setting the metric flag has been added to the define()
function as an additional function input. The fortran and c code has been updated to
reflect the removal of the function. No updates were made to the define function in
the fortran and c code.

The units.test file was also updated with new tests. Old tests were updated, removing
derived units from the list of compatible units. When searching for micro-meters (um),
compatible units of (A,in,m) will be provided instead of (A,in,m,um).

Location:
trunk/src/core
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/RpDict.h

    r544 r568  
    1414//#include <malloc.h>
    1515
    16 #ifndef _RpDICT_H 
     16#ifndef _RpDICT_H
    1717#define _RpDICT_H
    1818
     
    3434            class _Compare=std::equal_to<KeyType> >
    3535    class RpDictIterator;
     36
     37
    3638/*
    3739 * RpDictEntry should not depend on _Compare,
    38  * it was originally neede because RpDict is a friend class
     40 * it was originally needed because RpDict is a friend class
    3941 * then i needed to assign it a default value because RpUnits.cc
    4042 * uses it in its find function. RpUnits::find should really not
     
    237239    public:
    238240
     241        typedef bool (*RpDictHint)(ValType);
    239242
    240243        // functionality for the user to access/adjust data members
     
    250253                        set(    KeyType& key,
    251254                                ValType& value,
     255                                RpDictHint hint=NULL,
    252256                                int *newPtr=NULL,
    253257                                bool ci=false);
     
    255259        // find an RpUnits object that should exist in RpUnitsTable
    256260        //
    257         /*virtual*/ RpDictEntry<KeyType,ValType,_Compare>&
    258                         find( KeyType& key );
     261        /*virtual*/ RpDictEntry<KeyType,ValType,_Compare>&
     262                        find(   KeyType& key,
     263                                RpDictHint hint = NULL,
     264                                bool ci=false   );
    259265
    260266        /*virtual*/ RpDictEntry<KeyType,ValType,_Compare>& operator[]( KeyType& key)
    261267        {
    262             return find(key);
     268            return find(key,NULL);
    263269        }
    264270
     
    356362        // private member fxns
    357363
     364        RpDictEntry<KeyType,ValType,_Compare>*
     365            search( KeyType& key, RpDictHint hint = NULL, bool ci = false );
     366
    358367        // static void RpDict::RebuildTable ();
    359368        void RebuildTable ();
     
    416425RpDict<KeyType,ValType,_Compare>::set(  KeyType& key,
    417426                                        ValType& value,
     427                                        RpDictHint hint,
    418428                                        int* newPtr,
    419429                                        bool ci )
     
    427437    assert(&value);
    428438
    429     // take care of the case where we are creating a NULL key entry.
     439    hPtr = search(key,hint,ci);
     440    if (hPtr != NULL) {
     441        // adjust the new flag if it was provided
     442        if (newPtr) {
     443            *newPtr = 0;
     444        }
     445
     446        // adjust the value if it was provided
     447        // memory management is left as an exercise for the caller
     448        if (&value) {
     449            hPtr->setValue(value);
     450        }
     451
     452        // return a reference to the dictionary object
     453        return *this;
     454    }
     455
     456    /*
     457     * Entry not found.  Add a new one to the bucket.
     458     */
     459
    430460    if (&key) {
    431461        if (ci != oldCI) {
     
    438468    }
    439469    else {
     470        // we are creating a NULL key entry.
    440471        hash = 0;
    441472    }
    442473
    443474    index = randomIndex(hash);
    444 
    445     /*
    446      * Search all of the entries in the appropriate bucket.
    447      */
    448     for (hPtr = buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) {
    449         if (hash != (unsigned int) hPtr->hash) {
    450             continue;
    451         }
    452         // if element already exists in hash, it should not be re-entered
    453         // if (key == *(hPtr->getKey())){
    454         if (_Compare()(key, *(hPtr->getKey()))){
    455 
    456             // adjust the new flag if it was provided
    457             if (newPtr) {
    458                 *newPtr = 0;
    459             }
    460 
    461             // adjust the value if it was provided
    462             // memory management is left as an exercise for the caller
    463             if (&value) {
    464                 hPtr->setValue(value);
    465             }
    466 
    467             // return a reference to the dictionary object
    468             return *this;
    469         }
    470     }
    471 
    472     /*
    473      * Entry not found.  Add a new one to the bucket.
    474      */
    475 
    476     if (newPtr) {
    477         *newPtr = 1;
    478     }
    479475
    480476    hPtr = new RpDictEntry<KeyType,ValType,_Compare>(key,value);
     
    490486    numEntries++;
    491487
     488    if (newPtr) {
     489        *newPtr = 1;
     490    }
     491
    492492    /*
    493493     * If the table has exceeded a decent size, rebuild it with many
     
    503503}
    504504
    505 
    506 /*
    507  *----------------------------------------------------------------------
    508  *
    509  *  RpDict::find(const char *key)
     505/*
     506 *----------------------------------------------------------------------
     507 *
     508 *  RpDict::find(KeyType& key, RpDictHint hint)
    510509 *
    511510 *  Given a hash table find the entry with a matching key.
     
    523522template <typename KeyType, typename ValType, class _Compare>
    524523RpDictEntry<KeyType,ValType,_Compare>&
    525 RpDict<KeyType,ValType,_Compare>::find(KeyType& key)
     524RpDict<KeyType,ValType,_Compare>::find( KeyType& key,
     525                                        RpDictHint hint,
     526                                        bool ci )
    526527{
    527528    RpDictEntry<KeyType,ValType,_Compare> *hPtr = NULL;
    528     unsigned int hash = 0;
    529     int index = 0;
    530 
    531     assert(&key);
    532 
    533     // take care of the case where we are creating a NULL key entry.
    534     if (&key) {
    535         hash = (unsigned int) hashFxn(&key);
    536     }
    537     else {
    538         hash = 0;
    539     }
    540 
    541     index = randomIndex(hash);
    542 
    543     /*
    544      * Search all of the entries in the appropriate bucket.
    545      */
    546 
    547     for (hPtr = buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) {
    548         if (hash != (unsigned int) hPtr->hash) {
    549             continue;
    550         }
    551         // if (key == *(hPtr->getKey())) {
    552         if (_Compare()(key, *(hPtr->getKey()))){
    553             // return a reference to the found object
    554             return *hPtr;
    555         }
     529
     530    hPtr = search(key,hint,ci);
     531
     532    if (hPtr != NULL) {
     533        return *hPtr;
    556534    }
    557535
     
    560538    // changing this entry's data members... what to do?
    561539    return *nullEntry;
     540}
     541
     542/*
     543 *----------------------------------------------------------------------
     544 *
     545 *  RpDict::search(KeyType& key, RpDictHint hint)
     546 *
     547 *  Given a hash table find the entry with a matching key.
     548 *
     549 * Results:
     550 *  The return value is a token for the matching entry in the
     551 *  hash table, or NULL if there was no matching entry.
     552 *
     553 * Side effects:
     554 *  None.
     555 *
     556 *----------------------------------------------------------------------
     557 */
     558
     559template <typename KeyType, typename ValType, class _Compare>
     560RpDictEntry<KeyType,ValType,_Compare>*
     561RpDict<KeyType,ValType,_Compare>::search(   KeyType& key,
     562                                            RpDictHint hint,
     563                                            bool ci )
     564                                            // bool ci,
     565                                            // RpDictEntryList* entryList)
     566{
     567    RpDictEntry<KeyType,ValType,_Compare> *hPtr = NULL;
     568    unsigned int hash = 0;
     569    int index = 0;
     570    bool oldCI = caseInsensitive;
     571
     572    assert(&key);
     573
     574    // take care of the case where we are creating a NULL key entry.
     575    if (&key) {
     576        if (ci != oldCI) {
     577            // toggle the case insensitivity of the dictionary
     578            setCI(ci);
     579        }
     580
     581        hash = (unsigned int) hashFxn(&key);
     582
     583        if (ci != oldCI) {
     584            // reset the case insensitivity of the dictionary
     585            setCI(oldCI);
     586        }
     587    }
     588    else {
     589        hash = 0;
     590    }
     591
     592    index = randomIndex(hash);
     593
     594    /*
     595     * Search all of the entries in the appropriate bucket.
     596     */
     597
     598    for (hPtr = buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) {
     599        if (hash != (unsigned int) hPtr->hash) {
     600            continue;
     601        }
     602        if (_Compare()(key, *(hPtr->getKey()))) {
     603            // check to see if the user provided a hint
     604            if (hint != NULL ) {
     605                // if there is a hint, run the potential return value
     606                // throught the hint function.
     607                if (hint(*(hPtr->getValue())) == true) {
     608                    // the hint approves of our choice of return values
     609                    // return a reference to the found object
     610                    return hPtr;
     611                }
     612            }
     613            else {
     614                // return a reference to the found object
     615                return hPtr;
     616            }
     617        }
     618    }
     619
     620    // return a reference to the null object
     621    // find is not supposed to return a const, but i dont want the user
     622    // changing this entry's data members... what to do?
     623    return hPtr;
    562624
    563625}
     
    601663 *************************************************************************/
    602664template <typename KeyType,typename ValType,class _Compare>
    603 RpDictEntry<KeyType,ValType,_Compare>* 
     665RpDictEntry<KeyType,ValType,_Compare>*
    604666RpDictIterator<KeyType,ValType,_Compare>::first()
    605667{
     
    626688
    627689template <typename KeyType,typename ValType,class _Compare>
    628 RpDictEntry<KeyType,ValType,_Compare>* 
    629 RpDictIterator<KeyType,ValType,_Compare>::next() 
     690RpDictEntry<KeyType,ValType,_Compare>*
     691RpDictIterator<KeyType,ValType,_Compare>::next()
    630692{
    631693    RpDictEntry<KeyType,ValType,_Compare>* hPtr = NULL;
  • trunk/src/core/RpUnits.cc

    r562 r568  
    77 * ======================================================================
    88 *  AUTHOR:  Derrick Kearney, Purdue University
    9  *  Copyright (c) 2004-2005  Purdue Research Foundation
     9 *  Copyright (c) 2004-2007  Purdue Research Foundation
    1010 *
    1111 *  See the file "license.terms" for information on usage and
     
    3535                    const RpUnits* basis,
    3636                    const std::string type,
     37                    bool metric,
    3738                    bool caseInsensitive    ) {
    3839
     
    4546    double exponent = 1;
    4647
     48    RpUnitsTypes::RpUnitsTypesHint hint = NULL;
     49
    4750    if (units.empty()) {
    4851        // raise error, user sent null units!
     
    5760
    5861    // check to see if the said unit can already be found in the dictionary
    59     if (RpUnits::find(units)) {
     62    hint = RpUnitsTypes::getTypeHint(type);
     63    if (RpUnits::find(units,hint)) {
    6064        return NULL;
    6165    }
     
    8387    }
    8488
    85     newRpUnit = new RpUnits(sendStr, exponent, basis, type, caseInsensitive);
     89    newRpUnit = new RpUnits(    sendStr,
     90                                exponent,
     91                                basis,
     92                                type,
     93                                metric,
     94                                caseInsensitive );
    8695    if (newRpUnit) {
    8796        insert(newRpUnit->getUnitsName(),newRpUnit);
     
    171180 */
    172181
    173 const RpUnits*
    174 RpUnits::grabUnits ( std::string inStr, int* offset) {
    175 
    176     const RpUnits* unit = NULL;
     182int
     183RpUnits::grabUnits (    std::string inStr,
     184                        int* offset,
     185                        const RpUnits** unit,
     186                        const RpUnits** prefix   ) {
     187
    177188    int len = inStr.length();
     189    std::string preStr = "";
     190
     191    if ( (unit == NULL) || (prefix == NULL) ) {
     192        // incorrect function call, return error
     193        return -1;
     194    }
     195
     196    *unit = NULL;
     197    *prefix = NULL;
    178198
    179199    while ( ! inStr.empty() ) {
    180         unit = RpUnits::find(inStr);
    181         if (unit) {
     200        *unit = RpUnits::find(inStr,&RpUnitsTypes::hintTypeNonPrefix);
     201        if (*unit) {
    182202            *offset = len - inStr.length();
     203
     204            if ((*unit)->metric) {
     205                RpUnits::checkMetricPrefix(preStr,offset,prefix);
     206            }
     207
    183208            break;
    184209        }
     210        preStr = preStr + inStr.substr(0,1);
    185211        inStr.erase(0,1);
    186212    }
    187213
    188     return unit;
    189 }
    190 
     214    return 0;
     215}
     216
     217/**********************************************************************/
     218// METHOD: checkMetrixPrefix()
     219/// Compare a string with available metric prefixes
     220/**
     221 * The metric prefix only has one or two letters before the main unit.
     222 * We take in the string of characters before the found unit and search
     223 * for the two characters closest to the found unit. If those two
     224 * characters are not found in the dictionary as a prefix, then we erase
     225 * the 0th character, and search for the 1th character. The 1th character
     226 * is the character closest to the found unit. If it is found as a prefix
     227 * in the dictionary, it is returned. If no prefix is found, NULL is
     228 * returned.
     229 */
     230
     231int
     232RpUnits::checkMetricPrefix  (   std::string inStr,
     233                                int* offset,
     234                                const RpUnits** prefix   ) {
     235
     236    int inStrLen = 0;
     237    std::string searchStr = "";
     238
     239    inStrLen = inStr.length();
     240
     241    if (inStrLen == 0) {
     242        // no prefix to search for, exit
     243        return 0;
     244    }
     245
     246    if (prefix == NULL) {
     247        // incorrect function call, return error
     248        return -1;
     249    }
     250
     251
     252    if (inStrLen > 2) {
     253        searchStr = inStr.substr( inStrLen-2 );
     254    }
     255    else {
     256        searchStr = inStr;
     257    }
     258
     259    *prefix = NULL;
     260
     261    *prefix = RpUnits::find(searchStr,&RpUnitsTypes::hintTypePrefix);
     262    if ( (*prefix) == NULL ) {
     263        // the two letter prefix was not found,
     264        // try the one letter prefix
     265        searchStr.erase(0,1);
     266        *prefix = RpUnits::find(searchStr,&RpUnitsTypes::hintTypePrefix);
     267    }
     268
     269    if (*prefix != NULL) {
     270        // if a prefix was found, adjust the offset to reflect
     271        // the need to erase the prefix as well as the unit name
     272        *offset = *offset - searchStr.length();
     273    }
     274
     275    return 0;
     276}
    191277
    192278/**********************************************************************/
     
    563649
    564650/**********************************************************************/
     651// METHOD: setMetric()
     652/// Set the metric flag of the object.
     653/**
     654 * Set the metric flag of the object
     655 */
     656
     657RpUnits&
     658RpUnits::setMetric(bool newVal) {
     659
     660    metric = newVal;
     661    return *this;
     662}
     663
     664/**********************************************************************/
    565665// METHOD: makeBasis()
    566666/// Convert a value into its RpUnits's basis.
     
    635735 */
    636736
     737/*
    637738int
    638 RpUnits::makeMetric(const RpUnits* basis) {
     739RpUnits::makeMetric(RpUnits* basis) {
    639740
    640741    if (!basis) {
     
    642743    }
    643744
    644     std::string basisName = basis->getUnitsName();
    645     std::string name;
    646 
    647     name = "d" + basisName;
    648     RpUnits * deci = RpUnits::define(name, basis, basis->type);
    649     RpUnits::define(deci, basis, deci2base, base2deci);
    650 
    651     name = "c" + basisName;
    652     RpUnits * centi = RpUnits::define(name, basis, basis->type);
    653     RpUnits::define(centi, basis, centi2base, base2centi);
    654 
    655     name = "m" + basisName;
    656     RpUnits * milli = RpUnits::define(name, basis, basis->type,
    657         !RPUNITS_CASE_INSENSITIVE);
    658     RpUnits::define(milli, basis, milli2base, base2milli);
    659 
    660     name = "u" + basisName;
    661     RpUnits * micro = RpUnits::define(name, basis, basis->type);
    662     RpUnits::define(micro, basis, micro2base, base2micro);
    663 
    664     name = "n" + basisName;
    665     RpUnits * nano  = RpUnits::define(name, basis, basis->type);
    666     RpUnits::define(nano, basis, nano2base, base2nano);
    667 
    668     name = "p" + basisName;
    669     RpUnits * pico  = RpUnits::define(name, basis, basis->type,
    670         !RPUNITS_CASE_INSENSITIVE);
    671     RpUnits::define(pico, basis, pico2base, base2pico);
    672 
    673     name = "f" + basisName;
    674     RpUnits * femto = RpUnits::define(name, basis, basis->type);
    675     RpUnits::define(femto, basis, femto2base, base2femto);
    676 
    677     name = "a" + basisName;
    678     RpUnits * atto  = RpUnits::define(name, basis, basis->type);
    679     RpUnits::define(atto, basis, atto2base, base2atto);
    680 
    681     name = "da" + basisName;
    682     RpUnits * deca  = RpUnits::define(name, basis, basis->type);
    683     RpUnits::define(deca, basis, deca2base, base2deca);
    684 
    685     name = "h" + basisName;
    686     RpUnits * hecto  = RpUnits::define(name, basis, basis->type);
    687     RpUnits::define(hecto, basis, hecto2base, base2hecto);
    688 
    689     name = "k" + basisName;
    690     RpUnits * kilo  = RpUnits::define(name, basis, basis->type);
    691     RpUnits::define(kilo, basis, kilo2base, base2kilo);
    692 
    693     name = "M" + basisName;
    694     RpUnits * mega  = RpUnits::define(name, basis, basis->type,
    695         !RPUNITS_CASE_INSENSITIVE);
    696     RpUnits::define(mega, basis, mega2base, base2mega);
    697 
    698     name = "G" + basisName;
    699     RpUnits * giga  = RpUnits::define(name, basis, basis->type);
    700     RpUnits::define(giga, basis, giga2base, base2giga);
    701 
    702     name = "T" + basisName;
    703     RpUnits * tera  = RpUnits::define(name, basis, basis->type);
    704     RpUnits::define(tera, basis, tera2base, base2tera);
    705 
    706     name = "P" + basisName;
    707     RpUnits * peta  = RpUnits::define(name, basis, basis->type,
    708         !RPUNITS_CASE_INSENSITIVE);
    709     RpUnits::define(peta, basis, peta2base, base2peta);
    710 
    711     name = "E" + basisName;
    712     RpUnits * exa  = RpUnits::define(name, basis, basis->type);
    713     RpUnits::define(exa, basis, exa2base, base2exa);
    714 
    715     return (1);
    716 }
    717 
     745    basis->setMetric(true);
     746
     747    return 0;
     748}
     749*/
    718750
    719751/**********************************************************************/
     
    724756
    725757const RpUnits*
    726 RpUnits::find(std::string key) {
    727 
    728     RpDictEntry<std::string,RpUnits*,_key_compare>* unitEntry = &(dict->getNullEntry());
    729     RpDictEntry<std::string,RpUnits*,_key_compare>* nullEntry = &(dict->getNullEntry());
     758RpUnits::find(std::string key,
     759        RpDict<std::string,RpUnits*,_key_compare>::RpDictHint hint ) {
     760
     761    RpDictEntry<std::string,RpUnits*,_key_compare>*
     762        unitEntry = &(dict->getNullEntry());
     763    RpDictEntry<std::string,RpUnits*,_key_compare>*
     764        nullEntry = &(dict->getNullEntry());
    730765    double exponent = 1;
    731766    int idx = 0;
     
    740775    }
    741776
    742     // pass 1 - look for the unit name as it was stated by the user
    743     unitEntry = &(dict->find(key));
     777    if (unitEntry == nullEntry) {
     778        // pass 1 - look for the unit name as it was stated by the user
     779        // dict->toggleCI();
     780        unitEntry = &(dict->find(key,hint,!RPUNITS_CASE_INSENSITIVE));
     781        // dict->toggleCI();
     782    }
    744783
    745784    if (unitEntry == nullEntry) {
    746785        // pass 2 - use case insensitivity to look for the unit
    747         dict->toggleCI();
    748         unitEntry = &(dict->find(key));
    749         dict->toggleCI();
     786        unitEntry = &(dict->find(key,hint,RPUNITS_CASE_INSENSITIVE));
    750787    }
    751788
     
    776813
    777814int
    778 // RpUnits::validate ( const std::string& inUnits,
    779815RpUnits::validate ( std::string& inUnits,
    780816                    std::string& type,
    781817                    std::list<std::string>* compatList ) {
    782818
    783     std::string myInUnits   = inUnits;
    784819    std::string sendUnitStr = "";
    785820    double exponent         = 1;
     
    876911    }
    877912
     913    if (prefix != NULL) {
     914        name << prefix->getUnits();
     915    }
     916
    878917    name << unit->getUnits();
    879918
     
    927966
    928967/**********************************************************************/
     968// METHOD: getPrefix()
     969/// Return the prefix of an RpUnitsListEntry.
     970/**
     971 */
     972
     973const RpUnits*
     974RpUnitsListEntry::getPrefix() const {
     975    return prefix;
     976}
     977
     978/**********************************************************************/
    929979// METHOD: printList()
    930980/// Traverse a RpUnitsList and print out the name of each element.
     
    9501000/**********************************************************************/
    9511001// METHOD: units2list()
    952 /// Split a string of units into a list of units with exponents.
     1002/// Split a string of units into a list of units with exponents and prefixes.
    9531003/**
    9541004 * Splits a string of units like cm2/kVns into a list of units like
     
    9711021    int err                 = 0;
    9721022    const RpUnits* unit     = NULL;
     1023    const RpUnits* prefix   = NULL;
    9731024
    9741025
     
    10091060        offset = RpUnits::grabUnitString(myInUnits);
    10101061
    1011         // if idx > length, then the grabUnitString went through the whole
     1062        // if offset > length, then the grabUnitString went through the whole
    10121063        // string and did not find a good string we could use as units.
    10131064        // this generally means the string was filled with non alphabetical
     
    10301081        // figure out if we have some defined units in that string
    10311082        sendUnitStr.str(myInUnits.substr(offset,std::string::npos));
    1032         unit = grabUnits(sendUnitStr.str(),&offset);
     1083        grabUnits(sendUnitStr.str(),&offset,&unit,&prefix);
    10331084        if (unit) {
    10341085            // a unit was found
    10351086            // add this unit to the list
    10361087            // erase the found unit's name from our search string
    1037             outList.push_front(RpUnitsListEntry(unit,exponent));
     1088            outList.push_front(RpUnitsListEntry(unit,exponent,prefix));
    10381089            if (type.compare("") == 0) {
    10391090                type = unit->getType();
     
    10881139/// Join a list of units into a string with proper exponents.
    10891140/**
    1090  * Joings a list of units like cm2, kV-1, ns-1, creating a string
     1141 * Joins a list of units like cm2, kV-1, ns-1, creating a string
    10911142 * like cm2/kVns.
    10921143 */
     
    12671318
    12681319    const RpUnits* toUnits = NULL;
     1320    const RpUnits* toPrefix = NULL;
    12691321    const RpUnits* fromUnits = NULL;
     1322    const RpUnits* fromPrefix = NULL;
    12701323
    12711324    std::string tmpNumVal = "";
     
    13831436    while ( (toIter != toUnitsList.end()) && (fromIter != fromUnitsList.end()) && (!convErr) ) {
    13841437        fromUnits = fromIter->getUnitsObj();
     1438        fromPrefix = fromIter->getPrefix();
    13851439        toUnits = toIter->getUnitsObj();
     1440        toPrefix = toIter->getPrefix();
    13861441
    13871442        cList.clear();
     1443
     1444        if (fromPrefix != NULL) {
     1445            cList.push_back(fromPrefix->convList->conv->convForwFxnPtr);
     1446        }
     1447
    13881448        convErr = fromUnits->getConvertFxnList(toUnits, cList);
     1449
     1450        if (toPrefix != NULL) {
     1451            cList.push_back(toPrefix->convList->conv->convBackFxnPtr);
     1452        }
    13891453
    13901454        if (convErr == 0) {
     
    16111675    int my_result = 0;
    16121676
     1677    RpUnitsTypes::RpUnitsTypesHint hint = NULL;
     1678
    16131679    // set *result to a default value
    16141680    if (result) {
     
    16421708    // original unit.
    16431709    if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
    1644         dictToUnit = find(toBasis->getUnitsName());
     1710        hint = RpUnitsTypes::getTypeHint(toBasis->getType());
     1711        dictToUnit = find(toBasis->getUnitsName(), hint);
    16451712    }
    16461713    else {
    1647         dictToUnit = find(toUnit->getUnitsName());
     1714        hint = RpUnitsTypes::getTypeHint(toUnit->getType());
     1715        dictToUnit = find(toUnit->getUnitsName(), hint);
    16481716    }
    16491717
     
    18071875    int my_result = 0;
    18081876
     1877    RpUnitsTypes::RpUnitsTypesHint hint = NULL;
     1878
    18091879    // set *result to a default value
    18101880    if (result) {
     
    18381908    // original unit.
    18391909    if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
    1840         dictToUnit = find(toBasis->getUnitsName());
     1910        hint = RpUnitsTypes::getTypeHint(toBasis->getType());
     1911        dictToUnit = find(toBasis->getUnitsName(), hint);
    18411912    }
    18421913    else {
    1843         dictToUnit = find(toUnit->getUnitsName());
     1914        hint = RpUnitsTypes::getTypeHint(toUnit->getType());
     1915        dictToUnit = find(toUnit->getUnitsName(), hint);
    18441916    }
    18451917
     
    20092081    // original unit.
    20102082    if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
    2011         dictToUnit = find(toBasis->getUnitsName());
     2083        dictToUnit = find(  toBasis->getUnitsName(),
     2084                            &RpUnitsTypes::hintTypeNonPrefix );
    20122085    }
    20132086    else {
    2014         dictToUnit = find(toUnit->getUnitsName());
     2087        dictToUnit = find(  toUnit->getUnitsName(),
     2088                            &RpUnitsTypes::hintTypeNonPrefix );
    20152089    }
    20162090
     
    21822256/**
    21832257 *
    2184  * elements of l2 are pushed onto l1 in the same order in which it
    2185  * exists in l2. l1 is changed in this function.
    2186  *
    21872258 * Returns an integer value of zero (0) on success
    21882259 * Returns non-zero value on failure.
     
    22112282
    22122283    int newRecord = 0;
    2213     // RpUnits* val = this;
    2214     // dict pointer
    2215     RpUnits::dict->set(key,val,&newRecord,val->getCI());
     2284    RpUnitsTypes::RpUnitsTypesHint hint = NULL;
     2285
     2286    if (val == NULL) {
     2287        return -1;
     2288    }
     2289
     2290    hint = RpUnitsTypes::getTypeHint(val->getType());
     2291
     2292    RpUnits::dict->set(key,val,hint,&newRecord,val->getCI());
     2293
    22162294    return newRecord;
    22172295}
     
    22982376        retVal = RpUnitsPreset::addPresetMass();
    22992377    }
     2378    else if (group.compare(RP_TYPE_PREFIX) == 0) {
     2379        retVal = RpUnitsPreset::addPresetPrefix();
     2380    }
    23002381    else if (group.compare(RP_TYPE_PRESSURE) == 0) {
    23012382        retVal = RpUnitsPreset::addPresetPressure();
     
    23222403    int result = 0;
    23232404
     2405    result += addPresetPrefix();
    23242406    result += addPresetTime();
    23252407    result += addPresetTemp();
     
    23322414    result += addPresetConcentration();
    23332415    result += addPresetMisc();
     2416
     2417    return 0;
     2418}
     2419
     2420
     2421/**********************************************************************/
     2422// METHOD: addPresetPrefix()
     2423///
     2424/**
     2425 * Defines the following unit prefixes:
     2426 *   deci        (d)
     2427 *   centi       (c)
     2428 *   milli       (m)
     2429 *   micro       (u)
     2430 *   nano        (n)
     2431 *   pico        (p)
     2432 *   femto       (f)
     2433 *   atto        (a)
     2434 *   deca        (da)
     2435 *   hecto       (h)
     2436 *   kilo        (k)
     2437 *   mega        (M)
     2438 *   giga        (G)
     2439 *   tera        (T)
     2440 *   peta        (P)
     2441 *   exa         (E)
     2442 *
     2443 * Return codes: 0 success, anything else is error
     2444 */
     2445
     2446int
     2447RpUnitsPreset::addPresetPrefix () {
     2448
     2449    std::string type = RP_TYPE_PREFIX;
     2450    RpUnits* basis = NULL;
     2451
     2452    RpUnits * deci  = NULL;
     2453    RpUnits * centi = NULL;
     2454    RpUnits * milli = NULL;
     2455    RpUnits * micro = NULL;
     2456    RpUnits * nano  = NULL;
     2457    RpUnits * pico  = NULL;
     2458    RpUnits * femto = NULL;
     2459    RpUnits * atto  = NULL;
     2460    RpUnits * deca  = NULL;
     2461    RpUnits * hecto = NULL;
     2462    RpUnits * kilo  = NULL;
     2463    RpUnits * mega  = NULL;
     2464    RpUnits * giga  = NULL;
     2465    RpUnits * tera  = NULL;
     2466    RpUnits * peta  = NULL;
     2467    RpUnits * exa   = NULL;
     2468
     2469    deci  = RpUnits::define ( "d",  basis, type);
     2470    centi = RpUnits::define ( "c",  basis, type);
     2471    milli = RpUnits::define ( "m",  basis, type, !RPUNITS_METRIC,
     2472                              !RPUNITS_CASE_INSENSITIVE);
     2473    micro = RpUnits::define ( "u",  basis, type);
     2474    nano  = RpUnits::define ( "n",  basis, type);
     2475    pico  = RpUnits::define ( "p",  basis, type, !RPUNITS_METRIC,
     2476                              !RPUNITS_CASE_INSENSITIVE);
     2477    femto = RpUnits::define ( "f",  basis, type);
     2478    atto  = RpUnits::define ( "a",  basis, type);
     2479    deca  = RpUnits::define ( "da", basis, type);
     2480    hecto = RpUnits::define ( "h",  basis, type);
     2481    kilo  = RpUnits::define ( "k",  basis, type);
     2482    mega  = RpUnits::define ( "M",  basis, type, !RPUNITS_METRIC,
     2483                              !RPUNITS_CASE_INSENSITIVE);
     2484    giga  = RpUnits::define ( "G",  basis, type);
     2485    tera  = RpUnits::define ( "T",  basis, type);
     2486    peta  = RpUnits::define ( "P",  basis, type, !RPUNITS_METRIC,
     2487                              !RPUNITS_CASE_INSENSITIVE);
     2488    exa  = RpUnits::define  ( "E",  basis, type);
     2489
     2490    // the use of the unit as the from and the to unit is a hack
     2491    // that can be resolved by creating a RpPrefix object
     2492    // the define() function cannot handle NULL as to unit.
     2493    RpUnits::define ( deci,  deci , deci2base,  base2deci);
     2494    RpUnits::define ( centi, centi, centi2base, base2centi);
     2495    RpUnits::define ( milli, milli, milli2base, base2milli);
     2496    RpUnits::define ( micro, micro, micro2base, base2micro);
     2497    RpUnits::define ( nano,  nano , nano2base,  base2nano);
     2498    RpUnits::define ( pico,  pico , pico2base,  base2pico);
     2499    RpUnits::define ( femto, femto, femto2base, base2femto);
     2500    RpUnits::define ( atto,  atto , atto2base,  base2atto);
     2501    RpUnits::define ( deca,  deca , deca2base,  base2deca);
     2502    RpUnits::define ( hecto, hecto, hecto2base, base2hecto);
     2503    RpUnits::define ( kilo,  kilo , kilo2base,  base2kilo);
     2504    RpUnits::define ( mega,  mega , mega2base,  base2mega);
     2505    RpUnits::define ( giga,  giga , giga2base,  base2giga);
     2506    RpUnits::define ( tera,  tera , tera2base,  base2tera);
     2507    RpUnits::define ( peta,  peta , peta2base,  base2peta);
     2508    RpUnits::define ( exa,   exa  , exa2base,   base2exa);
    23342509
    23352510    return 0;
     
    23562531RpUnitsPreset::addPresetTime () {
    23572532
    2358     RpUnits* second    = RpUnits::define("s", NULL, RP_TYPE_TIME);
    2359     RpUnits* minute    = RpUnits::define("min", second, RP_TYPE_TIME);
    2360     RpUnits* hour      = RpUnits::define("h", second, RP_TYPE_TIME);
    2361     RpUnits* day       = RpUnits::define("d", second, RP_TYPE_TIME);
    2362 
    2363     RpUnits::makeMetric(second);
     2533    RpUnits* second    = NULL;
     2534    RpUnits* minute    = NULL;
     2535    RpUnits* hour      = NULL;
     2536    RpUnits* day       = NULL;
     2537
     2538    second    = RpUnits::define("s", NULL, RP_TYPE_TIME, RPUNITS_METRIC);
     2539    minute    = RpUnits::define("min", second, RP_TYPE_TIME);
     2540    hour      = RpUnits::define("h", second, RP_TYPE_TIME);
     2541    day       = RpUnits::define("d", second, RP_TYPE_TIME);
    23642542
    23652543    // add time definitions
     
    23882566RpUnitsPreset::addPresetTemp () {
    23892567
    2390     RpUnits* fahrenheit = RpUnits::define("F", NULL, RP_TYPE_TEMP);
    2391     RpUnits* celcius    = RpUnits::define("C", NULL, RP_TYPE_TEMP);
    2392     RpUnits* kelvin     = RpUnits::define("K", NULL, RP_TYPE_TEMP);
    2393     RpUnits* rankine    = RpUnits::define("R", NULL, RP_TYPE_TEMP);
     2568    RpUnits* fahrenheit = NULL;
     2569    RpUnits* celcius    = NULL;
     2570    RpUnits* kelvin     = NULL;
     2571    RpUnits* rankine    = NULL;
     2572
     2573    fahrenheit = RpUnits::define("F", NULL, RP_TYPE_TEMP);
     2574    celcius    = RpUnits::define("C", NULL, RP_TYPE_TEMP);
     2575    kelvin     = RpUnits::define("K", NULL, RP_TYPE_TEMP);
     2576    rankine    = RpUnits::define("R", NULL, RP_TYPE_TEMP);
    23942577
    23952578    // add temperature definitions
     
    24212604RpUnitsPreset::addPresetLength () {
    24222605
    2423     RpUnits* meters     = RpUnits::define("m", NULL, RP_TYPE_LENGTH);
    2424     RpUnits* angstrom   = RpUnits::define("A", NULL, RP_TYPE_LENGTH);
    2425     RpUnits* inch       = RpUnits::define("in", NULL, RP_TYPE_LENGTH);
    2426     RpUnits* feet       = RpUnits::define("ft", inch, RP_TYPE_LENGTH);
    2427     RpUnits* yard       = RpUnits::define("yd", inch, RP_TYPE_LENGTH);
    2428 
    2429     RpUnits::makeMetric(meters);
     2606    RpUnits* meters     = NULL;
     2607    RpUnits* angstrom   = NULL;
     2608    RpUnits* inch       = NULL;
     2609    RpUnits* feet       = NULL;
     2610    RpUnits* yard       = NULL;
     2611
     2612    meters     = RpUnits::define("m", NULL, RP_TYPE_LENGTH, RPUNITS_METRIC);
     2613    angstrom   = RpUnits::define("A", NULL, RP_TYPE_LENGTH);
     2614    inch       = RpUnits::define("in", NULL, RP_TYPE_LENGTH);
     2615    feet       = RpUnits::define("ft", inch, RP_TYPE_LENGTH);
     2616    yard       = RpUnits::define("yd", inch, RP_TYPE_LENGTH);
     2617
     2618    // RpUnits::makeMetric(meters);
    24302619
    24312620    // add length definitions
     
    24522641RpUnitsPreset::addPresetEnergy () {
    24532642
    2454     RpUnits* eVolt      = RpUnits::define("eV", NULL, RP_TYPE_ENERGY);
    2455     RpUnits* joule      = RpUnits::define("J", NULL, RP_TYPE_ENERGY);
    2456 
    2457     RpUnits::makeMetric(eVolt);
    2458     RpUnits::makeMetric(joule);
     2643    RpUnits* eVolt      = NULL;
     2644    RpUnits* joule      = NULL;
     2645
     2646    eVolt      = RpUnits::define("eV", NULL, RP_TYPE_ENERGY, RPUNITS_METRIC);
     2647    joule      = RpUnits::define("J", NULL, RP_TYPE_ENERGY, RPUNITS_METRIC);
    24592648
    24602649    // add energy definitions
     
    24812670    // RpUnits* cubic_meter  = RpUnits::define("m3", NULL, RP_TYPE_VOLUME);
    24822671    // RpUnits* cubic_feet   = RpUnits::define("ft3", NULL, RP_TYPE_VOLUME);
    2483     RpUnits* us_gallon    = RpUnits::define("gal", NULL, RP_TYPE_VOLUME);
    2484     RpUnits* liter        = RpUnits::define("L", NULL, RP_TYPE_VOLUME);
     2672    RpUnits* us_gallon    = NULL;
     2673    RpUnits* liter        = NULL;
     2674
     2675    us_gallon    = RpUnits::define("gal", NULL, RP_TYPE_VOLUME);
     2676    liter        = RpUnits::define("L", NULL, RP_TYPE_VOLUME, RPUNITS_METRIC);
    24852677
    24862678    /*
     
    25062698    */
    25072699
    2508     RpUnits::makeMetric(liter);
     2700    // RpUnits::makeMetric(liter);
    25092701
    25102702
     
    25342726RpUnitsPreset::addPresetAngle () {
    25352727
    2536     RpUnits* degree  = RpUnits::define("deg",  NULL, RP_TYPE_ANGLE);
    2537     RpUnits* gradian = RpUnits::define("grad", NULL, RP_TYPE_ANGLE);
    2538     RpUnits* radian  = RpUnits::define("rad",  NULL, RP_TYPE_ANGLE);
    2539 
    2540     RpUnits::makeMetric(radian);
     2728    RpUnits* degree  = NULL;
     2729    RpUnits* gradian = NULL;
     2730    RpUnits* radian  = NULL;
     2731
     2732    degree  = RpUnits::define("deg",  NULL, RP_TYPE_ANGLE);
     2733    gradian = RpUnits::define("grad", NULL, RP_TYPE_ANGLE);
     2734    radian  = RpUnits::define("rad",  NULL, RP_TYPE_ANGLE, RPUNITS_METRIC);
    25412735
    25422736    // add angle definitions
     
    25612755RpUnitsPreset::addPresetMass () {
    25622756
    2563     RpUnits* gram  = RpUnits::define("g",  NULL, RP_TYPE_MASS);
    2564 
    2565     RpUnits::makeMetric(gram);
    2566 
    2567     // add mass definitions
     2757    RpUnits* gram  = NULL;
     2758
     2759    gram  = RpUnits::define("g", NULL, RP_TYPE_MASS, RPUNITS_METRIC);
    25682760
    25692761    return 0;
     
    25932785RpUnitsPreset::addPresetPressure () {
    25942786
    2595     RpUnits* atmosphere = RpUnits::define("atm", NULL, RP_TYPE_PRESSURE);
    2596     RpUnits* bar = RpUnits::define("bar", NULL, RP_TYPE_PRESSURE);
    2597     RpUnits* pascal = RpUnits::define("Pa", NULL, RP_TYPE_PRESSURE);
    2598     RpUnits* psi = RpUnits::define("psi", NULL, RP_TYPE_PRESSURE);
    2599     RpUnits* torr = RpUnits::define("torr", NULL, RP_TYPE_PRESSURE);
    2600     RpUnits* mmHg = RpUnits::define("mmHg", torr, RP_TYPE_PRESSURE);
    2601 
    2602     RpUnits::makeMetric(pascal);
    2603     RpUnits::makeMetric(bar);
     2787    RpUnits* atmosphere = NULL;
     2788    RpUnits* bar        = NULL;
     2789    RpUnits* pascal     = NULL;
     2790    RpUnits* psi        = NULL;
     2791    RpUnits* torr       = NULL;
     2792    RpUnits* mmHg       = NULL;
     2793
     2794    atmosphere  = RpUnits::define("atm", NULL, RP_TYPE_PRESSURE);
     2795    bar     = RpUnits::define("bar",  NULL, RP_TYPE_PRESSURE, RPUNITS_METRIC);
     2796    pascal  = RpUnits::define("Pa",   NULL, RP_TYPE_PRESSURE, RPUNITS_METRIC);
     2797    psi     = RpUnits::define("psi",  NULL, RP_TYPE_PRESSURE);
     2798    torr    = RpUnits::define("torr", NULL, RP_TYPE_PRESSURE);
     2799    mmHg    = RpUnits::define("mmHg", torr, RP_TYPE_PRESSURE);
    26042800
    26052801    RpUnits::define(bar,pascal,bar2Pa,Pa2bar);
     
    26352831RpUnitsPreset::addPresetConcentration () {
    26362832
    2637     RpUnits* pH  = RpUnits::define("pH",  NULL, RP_TYPE_CONC);
    2638     RpUnits* pOH = RpUnits::define("pOH",  NULL, RP_TYPE_CONC);
     2833    RpUnits* pH  = NULL;
     2834    RpUnits* pOH = NULL;
     2835
     2836    pH  = RpUnits::define("pH",  NULL, RP_TYPE_CONC);
     2837    pOH = RpUnits::define("pOH", NULL, RP_TYPE_CONC);
    26392838
    26402839    // add concentration definitions
     
    26572856RpUnitsPreset::addPresetMisc () {
    26582857
    2659     RpUnits* volt      = RpUnits::define("V",  NULL, RP_TYPE_EPOT);
    2660     RpUnits* mole      = RpUnits::define("mol",NULL, RP_TYPE_MISC);
    2661     RpUnits* hertz     = RpUnits::define("Hz", NULL, RP_TYPE_MISC);
    2662     RpUnits* becquerel = RpUnits::define("Bq", NULL, RP_TYPE_MISC);
     2858    RpUnits* volt      = NULL;
     2859    RpUnits* mole      = NULL;
     2860    RpUnits* hertz     = NULL;
     2861    RpUnits* becquerel = NULL;
     2862
     2863    volt      = RpUnits::define("V",  NULL, RP_TYPE_EPOT, RPUNITS_METRIC);
     2864    mole      = RpUnits::define("mol",NULL, RP_TYPE_MISC, RPUNITS_METRIC);
     2865    hertz     = RpUnits::define("Hz", NULL, RP_TYPE_MISC, RPUNITS_METRIC);
     2866    becquerel = RpUnits::define("Bq", NULL, RP_TYPE_MISC, RPUNITS_METRIC);
     2867
    26632868    // RpUnits* percent   = RpUnits::define("%",  NULL, RP_TYPE_MISC);
    26642869
    2665     RpUnits::makeMetric(volt);
    2666     RpUnits::makeMetric(mole);
    2667     RpUnits::makeMetric(hertz);
    2668     RpUnits::makeMetric(becquerel);
    2669 
    2670     // add misc definitions
    2671     // RpUnits::define(radian,gradian,rad2grad,grad2rad);
    2672 
    26732870    return 0;
     2871}
     2872
     2873RpUnitsTypes::RpUnitsTypesHint
     2874RpUnitsTypes::getTypeHint (std::string type) {
     2875
     2876    if (type.compare(RP_TYPE_ENERGY) == 0) {
     2877        return &RpUnitsTypes::hintTypeEnergy;
     2878    }
     2879    else if (type.compare(RP_TYPE_EPOT) == 0) {
     2880        return &RpUnitsTypes::hintTypeEPot;
     2881    }
     2882    else if (type.compare(RP_TYPE_LENGTH) == 0) {
     2883        return &RpUnitsTypes::hintTypeLength;
     2884    }
     2885    else if (type.compare(RP_TYPE_TEMP) == 0) {
     2886        return &RpUnitsTypes::hintTypeTemp;
     2887    }
     2888    else if (type.compare(RP_TYPE_TIME) == 0) {
     2889        return &RpUnitsTypes::hintTypeTime;
     2890    }
     2891    else if (type.compare(RP_TYPE_VOLUME) == 0) {
     2892        return &RpUnitsTypes::hintTypeVolume;
     2893    }
     2894    else if (type.compare(RP_TYPE_ANGLE) == 0) {
     2895        return &RpUnitsTypes::hintTypeAngle;
     2896    }
     2897    else if (type.compare(RP_TYPE_MASS) == 0) {
     2898        return &RpUnitsTypes::hintTypeMass;
     2899    }
     2900    else if (type.compare(RP_TYPE_PREFIX) == 0) {
     2901        return &RpUnitsTypes::hintTypePrefix;
     2902    }
     2903    else if (type.compare(RP_TYPE_PRESSURE) == 0) {
     2904        return &RpUnitsTypes::hintTypePressure;
     2905    }
     2906    else if (type.compare(RP_TYPE_CONC) == 0) {
     2907        return &RpUnitsTypes::hintTypeConc;
     2908    }
     2909    else if (type.compare(RP_TYPE_MISC) == 0) {
     2910        return &RpUnitsTypes::hintTypeMisc;
     2911    }
     2912    else {
     2913        return NULL;
     2914    }
     2915};
     2916
     2917bool
     2918RpUnitsTypes::hintTypePrefix   (   RpUnits* unitObj    ) {
     2919
     2920    bool retVal = false;
     2921
     2922    if ( (unitObj->getType()).compare(RP_TYPE_PREFIX) == 0 ) {
     2923        retVal = true;
     2924    }
     2925
     2926    return retVal;
     2927}
     2928
     2929bool
     2930RpUnitsTypes::hintTypeNonPrefix    (   RpUnits* unitObj    ) {
     2931
     2932    bool retVal = true;
     2933
     2934    if ( (unitObj->getType()).compare(RP_TYPE_PREFIX) == 0 ) {
     2935        retVal = false;
     2936    }
     2937
     2938    return retVal;
     2939}
     2940
     2941bool
     2942RpUnitsTypes::hintTypeEnergy   (   RpUnits* unitObj    ) {
     2943
     2944    bool retVal = false;
     2945
     2946    if ( (unitObj->getType()).compare(RP_TYPE_ENERGY) == 0 ) {
     2947        retVal = true;
     2948    }
     2949
     2950    return retVal;
     2951}
     2952
     2953bool
     2954RpUnitsTypes::hintTypeEPot   (   RpUnits* unitObj    ) {
     2955
     2956    bool retVal = false;
     2957
     2958    if ( (unitObj->getType()).compare(RP_TYPE_EPOT) == 0 ) {
     2959        retVal = true;
     2960    }
     2961
     2962    return retVal;
     2963}
     2964
     2965bool
     2966RpUnitsTypes::hintTypeLength   (   RpUnits* unitObj    ) {
     2967
     2968    bool retVal = false;
     2969
     2970    if ( (unitObj->getType()).compare(RP_TYPE_LENGTH) == 0 ) {
     2971        retVal = true;
     2972    }
     2973
     2974    return retVal;
     2975}
     2976
     2977bool
     2978RpUnitsTypes::hintTypeTemp   (   RpUnits* unitObj    ) {
     2979
     2980    bool retVal = false;
     2981
     2982    if ( (unitObj->getType()).compare(RP_TYPE_TEMP) == 0 ) {
     2983        retVal = true;
     2984    }
     2985
     2986    return retVal;
     2987}
     2988
     2989bool
     2990RpUnitsTypes::hintTypeTime   (   RpUnits* unitObj    ) {
     2991
     2992    bool retVal = false;
     2993
     2994    if ( (unitObj->getType()).compare(RP_TYPE_TIME) == 0 ) {
     2995        retVal = true;
     2996    }
     2997
     2998    return retVal;
     2999}
     3000
     3001bool
     3002RpUnitsTypes::hintTypeVolume   (   RpUnits* unitObj    ) {
     3003
     3004    bool retVal = false;
     3005
     3006    if ( (unitObj->getType()).compare(RP_TYPE_VOLUME) == 0 ) {
     3007        retVal = true;
     3008    }
     3009
     3010    return retVal;
     3011}
     3012
     3013bool
     3014RpUnitsTypes::hintTypeAngle   (   RpUnits* unitObj    ) {
     3015
     3016    bool retVal = false;
     3017
     3018    if ( (unitObj->getType()).compare(RP_TYPE_ANGLE) == 0 ) {
     3019        retVal = true;
     3020    }
     3021
     3022    return retVal;
     3023}
     3024
     3025bool
     3026RpUnitsTypes::hintTypeMass   (   RpUnits* unitObj    ) {
     3027
     3028    bool retVal = false;
     3029
     3030    if ( (unitObj->getType()).compare(RP_TYPE_MASS) == 0 ) {
     3031        retVal = true;
     3032    }
     3033
     3034    return retVal;
     3035}
     3036
     3037bool
     3038RpUnitsTypes::hintTypePressure   (   RpUnits* unitObj    ) {
     3039
     3040    bool retVal = false;
     3041
     3042    if ( (unitObj->getType()).compare(RP_TYPE_PRESSURE) == 0 ) {
     3043        retVal = true;
     3044    }
     3045
     3046    return retVal;
     3047}
     3048
     3049bool
     3050RpUnitsTypes::hintTypeConc   (   RpUnits* unitObj    ) {
     3051
     3052    bool retVal = false;
     3053
     3054    if ( (unitObj->getType()).compare(RP_TYPE_CONC) == 0 ) {
     3055        retVal = true;
     3056    }
     3057
     3058    return retVal;
     3059}
     3060
     3061bool
     3062RpUnitsTypes::hintTypeMisc   (   RpUnits* unitObj    ) {
     3063
     3064    bool retVal = false;
     3065
     3066    if ( (unitObj->getType()).compare(RP_TYPE_MISC) == 0 ) {
     3067        retVal = true;
     3068    }
     3069
     3070    return retVal;
    26743071}
    26753072
  • trunk/src/core/RpUnits.h

    r562 r568  
    77 * ======================================================================
    88 *  AUTHOR:  Derrick Kearney, Purdue University
    9  *  Copyright (c) 2004-2005  Purdue Research Foundation
     9 *  Copyright (c) 2004-2007  Purdue Research Foundation
    1010 *
    1111 *  See the file "license.terms" for information on usage and
     
    3030// RpUnits Case Insensitivity define
    3131#define RPUNITS_CASE_INSENSITIVE true
    32 //
     32
     33#define RPUNITS_METRIC          true
     34
    3335//define our different types of units
    3436#define RP_TYPE_ENERGY      "energy"
     
    4042#define RP_TYPE_ANGLE       "angle"
    4143#define RP_TYPE_MASS        "mass"
     44#define RP_TYPE_PREFIX      "prefix"
    4245#define RP_TYPE_PRESSURE    "pressure"
    4346#define RP_TYPE_CONC        "concentration"
     
    6871        };
    6972
    70         static int addPresetAll();
    71         static int addPresetEnergy();
    72         static int addPresetLength();
    73         static int addPresetTemp();
    74         static int addPresetTime();
    75         static int addPresetVolume();
    76         static int addPresetAngle();
    77         static int addPresetMass();
    78         static int addPresetPressure();
    79         static int addPresetConcentration();
    80         static int addPresetMisc();
     73        static int  addPresetAll();
     74        static int  addPresetEnergy();
     75        static int  addPresetLength();
     76        static int  addPresetTemp();
     77        static int  addPresetTime();
     78        static int  addPresetVolume();
     79        static int  addPresetAngle();
     80        static int  addPresetMass();
     81        static int  addPresetPrefix();
     82        static int  addPresetPressure();
     83        static int  addPresetConcentration();
     84        static int  addPresetMisc();
     85};
     86
     87class RpUnitsTypes {
     88    public:
     89
     90        typedef bool (*RpUnitsTypesHint)(RpUnits*);
     91        static RpUnitsTypesHint getTypeHint (std::string type);
     92
     93        static bool hintTypePrefix    ( RpUnits* unitObj );
     94        static bool hintTypeNonPrefix ( RpUnits* unitObj );
     95        static bool hintTypeEnergy    ( RpUnits* unitObj );
     96        static bool hintTypeEPot      ( RpUnits* unitObj );
     97        static bool hintTypeLength    ( RpUnits* unitObj );
     98        static bool hintTypeTemp      ( RpUnits* unitObj );
     99        static bool hintTypeTime      ( RpUnits* unitObj );
     100        static bool hintTypeVolume    ( RpUnits* unitObj );
     101        static bool hintTypeAngle     ( RpUnits* unitObj );
     102        static bool hintTypeMass      ( RpUnits* unitObj );
     103        static bool hintTypePressure  ( RpUnits* unitObj );
     104        static bool hintTypeConc      ( RpUnits* unitObj );
     105        static bool hintTypeMisc      ( RpUnits* unitObj );
     106
     107    private:
     108
     109        RpUnitsTypes () {};
    81110};
    82111
     
    281310
    282311        // constructor
    283         RpUnitsListEntry (const RpUnits* unit, double exponent)
     312        RpUnitsListEntry (const RpUnits* unit, double exponent, const RpUnits* prefix=NULL)
    284313            : unit     (unit),
    285               exponent (exponent)
     314              exponent (exponent),
     315              prefix   (prefix)
    286316        {};
    287317
     
    289319        RpUnitsListEntry (const RpUnitsListEntry& other)
    290320            : unit     (other.unit),
    291               exponent (other.exponent)
     321              exponent (other.exponent),
     322              prefix   (other.prefix)
    292323        {};
    293324
     
    296327            unit = other.unit;
    297328            exponent = other.exponent;
     329            prefix = other.prefix;
    298330            return *this;
    299331        }
     
    313345        // return the exponent
    314346        double getExponent() const;
     347
     348        // return the metric prefix associated with this object
     349        const RpUnits* getPrefix() const;
    315350
    316351        // destructor
     
    322357        const RpUnits* unit;
    323358        mutable double exponent;
     359        const RpUnits* prefix;
    324360};
    325361
     
    336372    public:
    337373
     374        static bool cmpFxn (char c1, char c2)
     375        {
     376            int lc1 = toupper(static_cast<unsigned char>(c1));
     377            int lc2 = toupper(static_cast<unsigned char>(c2));
     378
     379            if ( (lc1 < lc2) || (lc1 > lc2) ) {
     380                return false;
     381            }
     382
     383            return true;
     384
     385        }
     386        struct _key_compare:
     387            public
     388            std::binary_function<std::string,std::string,bool> {
     389
     390                bool operator() (   const std::string& lhs,
     391                                    const std::string& rhs ) const
     392                {
     393                    return std::lexicographical_compare( lhs.begin(),lhs.end(),
     394                                                         rhs.begin(),rhs.end(),
     395                                                         RpUnits::cmpFxn  );
     396                }
     397            };
     398
     399        // why are these functions friends...
     400        // probably need to find a better way to let RpUnits
     401        // use the RpDict and RpDictEntry fxns
     402        friend class RpDict<std::string,RpUnits*,_key_compare>;
     403        friend class RpDictEntry<std::string,RpUnits*,_key_compare>;
    338404        // users member fxns
    339405        std::string getUnits() const;
     
    342408        double getExponent() const;
    343409        const RpUnits* getBasis() const;
     410        RpUnits& setMetric(bool newVal);
    344411
    345412        // retrieve a units type.
     
    358425                                int* result=NULL    ) const;
    359426        // convert from one RpUnits to another if the conversion is defined
    360         void* convert(          const RpUnits* toUnits, 
    361                                 void* val, 
     427        void* convert(          const RpUnits* toUnits,
     428                                void* val,
    362429                                int* result=NULL) const;
    363430        // convert from one RpUnits to another if the conversion is defined
     
    380447        const RpUnits & makeBasis(double* value, int* result = NULL) const;
    381448
    382         static int makeMetric(const RpUnits * basis);
     449        static int makeMetric(RpUnits * basis);
    383450
    384451        // find a RpUnits object that should exist in RpUnitsTable
    385452        // returns 0 on success (object was found)
    386453        // returns !0 on failure (object not found)
    387         static const RpUnits* find(std::string key);
    388 
    389         // validate is very similar to find, but it works better
    390         // for seeing complex units can be interpreted.
     454        static const RpUnits* find( std::string key,
     455        RpDict<std::string,RpUnits*,_key_compare>::RpDictHint hint = NULL);
     456
     457        // validate is very similar to find, but it works better
     458        // for seeing complex units can be interpreted.
    391459        // it validates that if the a certain units string is
    392460        // provided as a unit type, then all of the base components
     
    404472                                const RpUnits* basis=NULL,
    405473                                const std::string type="",
     474                                bool metric=false,
    406475                                bool caseInsensitive=RPUNITS_CASE_INSENSITIVE);
    407476
     
    439508        //  RP_TYPE_ANGLE    "angle"         load units related to angles
    440509        //  RP_TYPE_MASS     "mass"          load units related to mass
     510        //  RP_TYPE_PREFIX   "prefix"        load unit prefixes
    441511        //  RP_TYPE_PRESSURE "pressure"      load units related to pressure
    442512        //  RP_TYPE_CONC     "concentration" load units related to pressure
     
    449519        // int undefine(); // delete a relation
    450520
    451         static bool cmpFxn (char c1, char c2)
    452         {
    453             int lc1 = toupper(static_cast<unsigned char>(c1));
    454             int lc2 = toupper(static_cast<unsigned char>(c2));
    455 
    456             if ( (lc1 < lc2) || (lc1 > lc2) ) {
    457                 return false;
    458             }
    459 
    460             return true;
    461 
    462         }
    463         struct _key_compare:
    464             public
    465             std::binary_function<std::string,std::string,bool> {
    466 
    467                 bool operator() (   const std::string& lhs,
    468                                     const std::string& rhs ) const
    469                 {
    470                     return std::lexicographical_compare( lhs.begin(),lhs.end(),
    471                                                          rhs.begin(),rhs.end(),
    472                                                          RpUnits::cmpFxn  );
    473                 }
    474             };
    475         // why are these functions friends...
    476         // probably need to find a better way to let RpUnits
    477         // use the RpDict and RpDictEntry fxns
    478         friend class RpDict<std::string,RpUnits*,_key_compare>;
    479         friend class RpDictEntry<std::string,RpUnits*,_key_compare>;
    480521
    481522        friend int insert(std::string key,RpUnits* val);
     
    488529              basis    (other.basis),
    489530              type     (other.type),
     531              metric   (other.metric),
    490532              ci       (other.ci),
    491533              convList (NULL)
     
    541583            basis = other.basis;
    542584            type = other.type;
     585            metric = other.metric;
    543586            ci = other.ci;
    544587
     
    617660        std::string type;
    618661
     662        // tell if the unit can accept metric prefixes
     663        bool metric;
     664
    619665        // should this unit be inserted as a case insensitive unit?
    620666        bool ci;
     
    648694                    const RpUnits* basis,
    649695                    const std::string type,
     696                    bool metric,
    650697                    bool caseInsensitive
    651698                )
    652             :   units       (units),
    653                 exponent    (exponent),
    654                 basis       (basis),
    655                 type        (type),
    656                 ci          (caseInsensitive),
    657                 convList    (NULL),
     699            :   units           (units),
     700                exponent        (exponent),
     701                basis           (basis),
     702                type            (type),
     703                metric          (metric),
     704                ci              (caseInsensitive),
     705                convList        (NULL),
    658706                incarnationList (NULL)
    659707        {};
     
    669717        typedef RpUnitsList::iterator RpUnitsListIter;
    670718
    671         void newExponent(double newExponent) {exponent = newExponent;};
    672 
    673         static int units2list( const std::string& inUnits,
    674                                RpUnitsList& outList,
    675                                std::string& type);
    676         static int list2units( RpUnitsList& inList,
    677                                std::string& outUnitsStr);
    678         static int grabExponent(const std::string& inStr, double* exp);
    679         static int grabUnitString( const std::string& inStr);
    680         static const RpUnits* grabUnits (std::string inStr, int* offset);
    681         static int negateListExponents(RpUnitsList& unitsList);
    682         static int printList(RpUnitsList& unitsList);
    683 
    684         static int compareListEntryBasis( RpUnitsList& fromList,
    685                                           RpUnitsListIter& fromIter,
    686                                           RpUnitsListIter& toIter);
    687 
    688         static int compareListEntrySearch( RpUnitsList& fromList,
    689                                            RpUnitsListIter& fromIter,
    690                                            RpUnitsListIter& toIter);
    691 
    692         void connectConversion(conversion* conv) const;
    693         void connectIncarnation(const RpUnits* unit) const;
     719        // void newExponent                (double newExponent) {exponent = newExponent;};
     720
     721        static int      units2list          ( const std::string& inUnits,
     722                                              RpUnitsList& outList,
     723                                              std::string& type         );
     724        static int      list2units          ( RpUnitsList& inList,
     725                                              std::string& outUnitsStr  );
     726        static int      grabExponent        ( const std::string& inStr,
     727                                              double* exp               );
     728        static int      grabUnitString      ( const std::string& inStr  );
     729        static int      grabUnits           ( std::string inStr,
     730                                              int* offset,
     731                                              const RpUnits** unit,
     732                                              const RpUnits** prefix    );
     733        static int      checkMetricPrefix   ( std::string inStr,
     734                                              int* offset,
     735                                              const RpUnits** prefix    );
     736        static int      negateListExponents ( RpUnitsList& unitsList    );
     737        static int      printList           ( RpUnitsList& unitsList    );
     738
     739        static int compareListEntryBasis    ( RpUnitsList& fromList,
     740                                              RpUnitsListIter& fromIter,
     741                                              RpUnitsListIter& toIter   );
     742
     743        static int compareListEntrySearch   ( RpUnitsList& fromList,
     744                                              RpUnitsListIter& fromIter,
     745                                              RpUnitsListIter& toIter   );
     746
     747        void            connectConversion   ( conversion* conv      ) const;
     748        void            connectIncarnation  ( const RpUnits* unit   ) const;
    694749
    695750        // return the conversion object that will convert
    696751        // from this RpUnits to the proovided toUnits object
    697752        // if the conversion is defined
    698         int getConvertFxnList (const RpUnits* toUnits, convertList& cList) const;
    699         static int applyConversion (double* val, convertList& cList);
    700         static int combineLists (convertList& l1, convertList& l2);
    701         static int printList (convertList& l1);
     753        int             getConvertFxnList   ( const RpUnits* toUnits,
     754                                              convertList& cList    ) const;
     755        static int      applyConversion     ( double* val,
     756                                              convertList& cList    );
     757        static int      combineLists        ( convertList& l1,
     758                                              convertList& l2       );
     759        static int      printList           ( convertList& l1       );
    702760
    703761};
Note: See TracChangeset for help on using the changeset viewer.