Changeset 534


Ignore:
Timestamp:
Oct 9, 2006 12:41:16 PM (18 years ago)
Author:
dkearney
Message:

added incarnate functionality to units objects so we can begin to think about conversions like m3<->L.
added new algorithm for applying conversion functions.
added concentration (pH and pOH) and several other units.
added/fixed several units conversion functions.

Location:
trunk/src/core
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/RpUnits.cc

    r525 r534  
    9393
    9494/**********************************************************************/
     95// METHOD: incarnate()
     96/// Link two RpUnits where the entity is an incarnate of the abstraction
     97/**
     98 */
     99
     100int
     101RpUnits::incarnate(const RpUnits* abstraction, const RpUnits* entity) {
     102
     103    int retVal = 1;
     104
     105    abstraction->connectIncarnation(entity);
     106    entity->connectIncarnation(abstraction);
     107
     108    retVal = 0;
     109    return retVal;
     110}
     111
     112/**********************************************************************/
    95113// METHOD: grabExponent()
    96114/// Return exponent from a units string containing a unit name and exponent
     
    191209    std::list<std::string> compatList;
    192210    std::list<std::string> basisCompatList;
    193     std::string myName          = getUnitsName();
    194     // std::stringstream otherName;
    195     std::string otherName       = "";
     211    std::list<std::string> incarnationCompatList;
     212    std::stringstream myName;
     213    std::stringstream otherName;
    196214    std::string otherBasisName  = "";
    197215    std::string blank           = "";
    198     // double otherExp             = 1.0;
     216    double otherExp             = 1.0;
     217    double myExp                = 1.0;
     218    double incExp               = 1.0;
    199219    convEntry* myConversions    = this->convList;
     220    incarnationEntry* myIncarnations = this->incarnationList;
    200221    const RpUnits * basis       = NULL;
    201222
     223    myName.str("");
     224    myName << getUnits();
     225    myExp = getExponent() * expMultiplier;
     226
    202227    if (this->basis) {
    203         basisCompatList = this->basis->getCompatible();
     228        basisCompatList = this->basis->getCompatible(expMultiplier);
    204229        compatList.merge(basisCompatList);
    205230    }
     
    215240        while (myConversions != NULL) {
    216241
    217             otherName = myConversions->conv->toPtr->getUnitsName();
    218             /*
    219242            otherName.str("");
    220             otherName << myConversions->conv->toPtr->getUnitsName();
    221             otherExp = myConversions->conv->fromPtr->getExponent();
    222             if ( (otherExp != 1) && (expMultiplier != 1) ) {
    223                 otherName << otherExp * expMultiplier;
    224             }
    225             */
     243            // otherName << myConversions->conv->toPtr->getUnitsName();
     244            otherName << myConversions->conv->toPtr->getUnits();
     245            otherExp = myConversions->conv->toPtr->getExponent();
    226246            basis = myConversions->conv->toPtr->basis;
    227247
    228             // if (myName == otherName.str()) {
    229             if (myName == otherName) {
    230                 otherName = myConversions->conv->fromPtr->getUnitsName();
    231                 /*
     248            if (myName.str() == otherName.str()) {
    232249                otherName.str("");
    233                 otherName << myConversions->conv->fromPtr->getUnitsName();
    234                 if ( (otherExp != 1) && (expMultiplier != 1) ) {
    235                     otherExp = myConversions->conv->fromPtr->getExponent();
    236                     otherName << otherExp * expMultiplier;
    237                 }
    238                 */
     250                // otherName << myConversions->conv->fromPtr->getUnitsName();
     251                otherName << myConversions->conv->fromPtr->getUnits();
     252                otherExp = myConversions->conv->fromPtr->getExponent();
    239253                basis = myConversions->conv->fromPtr->basis;
    240254            }
     
    243257            // no need to list all of the metric conversions.
    244258            if (basis) {
    245                 if (basis->getUnitsName() == myName) {
     259                if (basis->getUnitsName() == myName.str()) {
    246260                    // do not add this unit to the conversion
    247261                    // because its a derived unit.
     
    251265            }
    252266
     267            // adjust the exponent as requested by fxn caller
     268            otherExp = otherExp * expMultiplier;
     269
     270            // adjust the other units name to match exponent
     271            if ( (otherExp > 0) && (otherExp != 1) ) {
     272                otherName << otherExp;
     273            }
     274            else if (otherExp < 0) {
     275                otherName.str("/"+otherName.str());
     276                if (otherExp < -1) {
     277                    otherName.seekp(0,std::ios_base::end);
     278                    otherName << otherExp*-1;
     279                }
     280            }
     281
    253282            // add the other unit's name to the list of compatible units
    254             // compatList.push_back(otherName.str());
    255             compatList.push_back(otherName);
     283            compatList.push_back(otherName.str());
     284            // compatList.push_back(otherName);
    256285
    257286            // advance to the next conversion
    258287            myConversions = myConversions->next;
    259288        }
    260     }
    261 
    262     compatList.push_back(myName);
     289
     290        // now go throught the incarnation list to see if there are other
     291        // compatible units listed there.
     292        while (myIncarnations != NULL) {
     293            incExp = myIncarnations->unit->getExponent();
     294            if (incExp == myExp) {
     295                incarnationCompatList = myIncarnations->unit->getCompatible();
     296                compatList.merge(incarnationCompatList);
     297                break;
     298            }
     299            else if ((-1.0*incExp) == myExp) {
     300                incarnationCompatList = myIncarnations->unit->getCompatible(-1);
     301                compatList.merge(incarnationCompatList);
     302                break;
     303            }
     304            else if (   (myExp == int(myExp))   &&
     305                        (incExp == int(incExp)) &&
     306                        ( (int(myExp)%int(incExp)) == 0) &&
     307                        ( (myExp/incExp) != 1)  &&
     308                        ( (myExp/incExp) != -1) &&
     309                        ( myExp != 1 )          &&
     310                        ( myExp != -1 )         &&
     311                        ( incExp != 1 )         &&
     312                        ( incExp != -1 )        ) {
     313                incarnationCompatList = myIncarnations->unit->getCompatible(myExp/incExp);
     314                compatList.merge(incarnationCompatList);
     315                break;
     316            }
     317            else {
     318                // do nothing
     319            }
     320            myIncarnations = myIncarnations->next;
     321        }
     322    }
     323
     324    // adjust the exponent as requested by fxn caller
     325    // myExp = myExp * expMultiplier;
     326
     327    // adjust the other units name to match exponent
     328    if ( (expMultiplier > 0) && (expMultiplier != 1) ) {
     329        // myName << expMultiplier;
     330        myName << myExp;
     331    }
     332    else if (expMultiplier < 0) {
     333        myName.str("/"+myName.str());
     334        if (myExp < -1) {
     335            myName.seekp(0,std::ios_base::end);
     336            myName << myExp*-1;
     337        }
     338    }
     339
     340    compatList.push_back(myName.str());
    263341    compatList.sort();
    264342    compatList.unique();
     
    266344
    267345}
     346
     347
     348
    268349
    269350/**********************************************************************/
     
    521602    std::string name;
    522603
     604    name = "d" + basisName;
     605    RpUnits * deci = RpUnits::define(name, basis, basis->type);
     606    RpUnits::define(deci, basis, deci2base, base2deci);
     607
    523608    name = "c" + basisName;
    524609    RpUnits * centi = RpUnits::define(name, basis, basis->type);
     
    549634    RpUnits::define(atto, basis, atto2base, base2atto);
    550635
     636    name = "da" + basisName;
     637    RpUnits * deca  = RpUnits::define(name, basis, basis->type);
     638    RpUnits::define(deca, basis, deca2base, base2deca);
     639
     640    name = "h" + basisName;
     641    RpUnits * hecto  = RpUnits::define(name, basis, basis->type);
     642    RpUnits::define(hecto, basis, hecto2base, base2hecto);
     643
    551644    name = "k" + basisName;
    552645    RpUnits * kilo  = RpUnits::define(name, basis, basis->type);
     
    568661    RpUnits * peta  = RpUnits::define(name, basis, basis->type);
    569662    RpUnits::define(peta, basis, peta2base, base2peta);
     663
     664    name = "E" + basisName;
     665    RpUnits * exa  = RpUnits::define(name, basis, basis->type);
     666    RpUnits::define(exa, basis, exa2base, base2exa);
    570667
    571668    return (1);
     
    618715 * returns error (a non-zero value).
    619716 *
    620  * this code is very similar to units2list()
    621  *
    622717 * if &compatList == NULL, no compatible list of units will be generated.
    623718 * this function does not do a good job of placing the available units
     
    633728    std::string sendUnitStr = "";
    634729    double exponent         = 1;
    635     int offset              = 0;
    636     int idx                 = 0;
    637     int last                = 0;
    638     int err                 = 0; // did we come across an unrecognized unit
     730    int err                 = 0;
    639731    const RpUnits* unit     = NULL;
    640732    std::list<std::string> basisCompatList;
    641733    std::list<std::string>::iterator compatListIter;
    642734    std::stringstream unitWExp;
     735    RpUnitsList inUnitsList;
     736    RpUnitsListIter inIter;
     737
     738    // err tells us if we encountered any unrecognized units
     739    err = RpUnits::units2list(inUnits,inUnitsList,type);
     740    inIter = inUnitsList.begin();
     741
     742    while ( inIter != inUnitsList.end() ) {
     743
     744        unit = inIter->getUnitsObj();
     745        exponent = inIter->getExponent();
     746
     747        // merge the compatible units
     748        if (compatList) {
     749
     750            basisCompatList = unit->getCompatible(exponent);
     751            compatList->merge(basisCompatList);
     752        }
     753
     754        inIter++;
     755    }
     756
     757    // clean out any duplicate entries.
     758    if (compatList) {
     759        compatList->unique();
     760    }
     761
     762    return err;
     763}
     764
     765
     766/**********************************************************************/
     767// METHOD: negateListExponents()
     768/// Negate the exponents on every element in unitsList
     769/**
     770 */
     771
     772int
     773RpUnits::negateListExponents(RpUnitsList& unitsList) {
     774    RpUnitsListIter iter = unitsList.begin();
     775    int nodeCnt = unitsList.size();
     776
     777    if (nodeCnt > 0) {
     778        for (; iter != unitsList.end(); iter++) {
     779            iter->negateExponent();
     780            nodeCnt--;
     781        }
     782    }
     783
     784    return nodeCnt;
     785}
     786
     787/**********************************************************************/
     788// METHOD: negateExponent()
     789/// Negate the exponent on the current RpUnitsListEntry
     790/**
     791 */
     792
     793void
     794RpUnitsListEntry::negateExponent() const {
     795    exponent = exponent * -1;
     796    return;
     797}
     798
     799/**********************************************************************/
     800// METHOD: name()
     801/// Provide the caller with the name of this object
     802/**
     803 */
     804
     805std::string
     806RpUnitsListEntry::name() const {
     807    std::stringstream name;
     808    name << unit->getUnits() << exponent;
     809    return std::string(name.str());
     810}
     811
     812/**********************************************************************/
     813// METHOD: define()
     814/// Provide the caller with the basis of the RpUnits object being stored
     815/**
     816 */
     817
     818const RpUnits*
     819RpUnitsListEntry::getBasis() const {
     820    return unit->getBasis();
     821}
     822
     823/**********************************************************************/
     824// METHOD: getUnitsObj()
     825/// Return the RpUnits Object from a RpUnitsListEntry.
     826/**
     827 */
     828
     829const RpUnits*
     830RpUnitsListEntry::getUnitsObj() const {
     831    return unit;
     832}
     833
     834/**********************************************************************/
     835// METHOD: getExponent()
     836/// Return the exponent of an RpUnitsListEntry.
     837/**
     838 */
     839
     840double
     841RpUnitsListEntry::getExponent() const {
     842    return exponent;
     843}
     844
     845/**********************************************************************/
     846// METHOD: printList()
     847/// Traverse a RpUnitsList and print out the name of each element.
     848/**
     849 */
     850
     851int
     852RpUnits::printList(RpUnitsList& unitsList) {
     853    RpUnitsListIter iter = unitsList.begin();
     854    int nodeCnt = unitsList.size();
     855
     856    if (nodeCnt > 0) {
     857        for (; iter != unitsList.end(); iter++) {
     858            std::cout << iter->name() << " ";
     859            nodeCnt--;
     860        }
     861        std::cout << std::endl;
     862    }
     863
     864    return nodeCnt;
     865}
     866
     867/**********************************************************************/
     868// METHOD: units2list()
     869/// Split a string of units into a list of base units with exponents.
     870/**
     871 * Splits a string of units like cm2/kVns into a list of units like
     872 * cm2, kV1, ns1 where an exponent is provided for each list entry.
     873 * List entries are found by comparing units strings to the names
     874 * in the dictionary.
     875 */
     876
     877int
     878RpUnits::units2list ( const std::string& inUnits,
     879                      RpUnitsList& outList,
     880                      std::string& type ) {
     881
     882    std::string myInUnits   = inUnits;
     883    std::stringstream sendUnitStr;
     884    double exponent         = 1;
     885    int offset              = 0;
     886    int idx                 = 0;
     887    int last                = 0;
     888    int err                 = 0;
     889    const RpUnits* unit     = NULL;
    643890
    644891
     
    650897            type = myInUnits[last] + type;
    651898            myInUnits.erase(last);
     899            // multiply previous exponents by -1
     900            if ( ! outList.empty() ) {
     901                RpUnits::negateListExponents(outList);
     902            }
    652903            continue;
    653904        }
     
    663914
    664915        // figure out if we have some defined units in that string
    665         sendUnitStr = myInUnits.substr(offset,std::string::npos);
    666         if ((unit = grabUnits(sendUnitStr,&offset))) {
    667             // a unit was found
    668             // erase the found unit's name from our search string
    669             myInUnits.erase(idx+offset);
    670 
    671             // add the type to the type string
    672             type = unit->getType() + type;
    673 
    674             // merge the compatible units
    675             if (compatList) {
    676                 basisCompatList = unit->getCompatible(exponent);
    677 
    678                 // adjust exponents as necessary
    679                 if ( (exponent != 0) && (exponent != 1) ) {
    680                     compatListIter = compatList->begin();
    681                     while (compatListIter != compatList->end()) {
    682                         unitWExp << *compatListIter << exponent;
    683                         *compatListIter = unitWExp.str();
    684                     }
    685                 }
    686 
    687                 compatList->merge(basisCompatList);
    688             }
    689         }
    690         else {
    691             // we came across a unit we did not recognize
    692             // raise error and exit
    693             err++;
    694             break;
    695         }
    696 
    697         // reset our vars
    698         idx = 0;
    699         offset = 0;
    700         exponent = 1;
    701     }
    702 
    703     // clean out any duplicate entries.
    704     if (compatList) {
    705         compatList->unique();
    706     }
    707 
    708     return err;
    709 }
    710 
    711 
    712 /**********************************************************************/
    713 // METHOD: negateListExponents()
    714 /// Negate the exponents on every element in unitsList
    715 /**
    716  */
    717 
    718 int
    719 RpUnits::negateListExponents(RpUnitsList& unitsList) {
    720     RpUnitsListIter iter = unitsList.begin();
    721     int nodeCnt = unitsList.size();
    722 
    723     if (nodeCnt > 0) {
    724         for (; iter != unitsList.end(); iter++) {
    725             iter->negateExponent();
    726             nodeCnt--;
    727         }
    728     }
    729 
    730     return nodeCnt;
    731 }
    732 
    733 /**********************************************************************/
    734 // METHOD: negateExponent()
    735 /// Negate the exponent on the current RpUnitsListEntry
    736 /**
    737  */
    738 
    739 void
    740 RpUnitsListEntry::negateExponent() const {
    741     exponent = exponent * -1;
    742     return;
    743 }
    744 
    745 /**********************************************************************/
    746 // METHOD: name()
    747 /// Provide the caller with the name of this object
    748 /**
    749  */
    750 
    751 std::string
    752 RpUnitsListEntry::name() const {
    753     std::stringstream name;
    754     name << unit->getUnits() << exponent;
    755     return std::string(name.str());
    756 }
    757 
    758 /**********************************************************************/
    759 // METHOD: define()
    760 /// Provide the caller with the basis of the RpUnits object being stored
    761 /**
    762  */
    763 
    764 const RpUnits*
    765 RpUnitsListEntry::getBasis() const {
    766     return unit->getBasis();
    767 }
    768 
    769 /**********************************************************************/
    770 // METHOD: getUnitsObj()
    771 /// Return the RpUnits Object from a RpUnitsListEntry.
    772 /**
    773  */
    774 
    775 const RpUnits*
    776 RpUnitsListEntry::getUnitsObj() const {
    777     return unit;
    778 }
    779 
    780 /**********************************************************************/
    781 // METHOD: getExponent()
    782 /// Return the exponent of an RpUnitsListEntry.
    783 /**
    784  */
    785 
    786 double
    787 RpUnitsListEntry::getExponent() const {
    788     return exponent;
    789 }
    790 
    791 /**********************************************************************/
    792 // METHOD: printList()
    793 /// Traverse a RpUnitsList and print out the name of each element.
    794 /**
    795  */
    796 
    797 int
    798 RpUnits::printList(RpUnitsList& unitsList) {
    799     RpUnitsListIter iter = unitsList.begin();
    800     int nodeCnt = unitsList.size();
    801 
    802     if (nodeCnt > 0) {
    803         for (; iter != unitsList.end(); iter++) {
    804             std::cout << iter->name() << " ";
    805             nodeCnt--;
    806         }
    807         std::cout << std::endl;
    808     }
    809 
    810     return nodeCnt;
    811 }
    812 
    813 /**********************************************************************/
    814 // METHOD: units2list()
    815 /// Split a string of units into a list of base units with exponents.
    816 /**
    817  * Splits a string of units like cm2/kVns into a list of units like
    818  * cm2, kV1, ns1 where an exponent is provided for each list entry.
    819  * List entries are found by comparing units strings to the names
    820  * in the dictionary.
    821  */
    822 
    823 int
    824 RpUnits::units2list ( const std::string& inUnits,
    825                       RpUnitsList& outList ) {
    826 
    827     std::string myInUnits   = inUnits;
    828     std::string sendUnitStr = "";
    829     double exponent         = 1;
    830     int offset              = 0;
    831     int idx                 = 0;
    832     int last                = 0;
    833     const RpUnits* unit     = NULL;
    834 
    835 
    836     while ( !myInUnits.empty() ) {
    837 
    838         // check to see if we came across a '/' character
    839         last = myInUnits.length()-1;
    840         if (myInUnits[last] == '/') {
    841             myInUnits.erase(last);
    842             // multiply previous exponents by -1
    843             if ( ! outList.empty() ) {
    844                 RpUnits::negateListExponents(outList);
    845             }
    846             continue;
    847         }
    848 
    849         // get the exponent
    850         offset = RpUnits::grabExponent(myInUnits,&exponent);
    851         myInUnits.erase(offset);
    852         idx = offset - 1;
    853 
    854         // grab the largest string we can find
    855         offset = RpUnits::grabUnitString(myInUnits);
    856         idx = offset;
    857 
    858         // figure out if we have some defined units in that string
    859         sendUnitStr = myInUnits.substr(offset,std::string::npos);
    860         unit = grabUnits(sendUnitStr,&offset);
     916        sendUnitStr.str(myInUnits.substr(offset,std::string::npos));
     917        unit = grabUnits(sendUnitStr.str(),&offset);
    861918        if (unit) {
    862919            // a unit was found
     
    864921            // erase the found unit's name from our search string
    865922            outList.push_front(RpUnitsListEntry(unit,exponent));
     923            type = unit->getType() + type;
    866924            myInUnits.erase(idx+offset);
    867925        }
     
    869927            // we came across a unit we did not recognize
    870928            // raise error and delete character for now
     929            err = 1;
    871930            myInUnits.erase(last);
    872931        }
     932
     933        /*
     934        // if the exponent != 1,-1 then do a second search
     935        // for the unit+exponent string that might be defined.
     936        // this is to cover the case were we have defined conversions
     937        // m3<->gal, m3<->L but m is defined
     938        if ( (exponent != 1) && (exponent != -1) ) {
     939            sendUnitStr.str("");
     940            sendUnitStr << unit->getUnits() << exponent;
     941            unit = grabUnits(sendUnitStr.str(),&offset);
     942            if (unit) {
     943                // a unit was found
     944                // add this unit to the list
     945                outList.push_front(RpUnitsListEntry(unit,1.0));
     946            }
     947            else {
     948                // we came across a unit we did not recognize
     949                // do nothing
     950            }
     951        }
     952        */
    873953
    874954        // reset our vars
     
    878958    }
    879959
    880     return 0;
     960    return err;
    881961}
    882962
     
    10061086 */
    10071087
     1088
    10081089std::string
    10091090RpUnits::convert (  std::string val,
     
    10251106    std::string fromUnitsName = "";
    10261107    std::string convVal = "";
     1108    std::string type = "";     // junk var used because units2list requires it
    10271109    double origNumVal = 0;
    10281110    double numVal = 0;
     
    10331115    std::stringstream outVal;
    10341116
    1035     int rv = 0;
    1036     double factor = 1;
     1117    double copies = 0;
     1118
     1119    convertList cList;
     1120    convertList totalConvList;
    10371121
    10381122
     
    11051189    }
    11061190
    1107     RpUnits::units2list(toUnitsName,toUnitsList);
    1108     RpUnits::units2list(fromUnitsName,fromUnitsList);
    1109 
     1191    RpUnits::units2list(fromUnitsName,fromUnitsList,type);
     1192    RpUnits::units2list(toUnitsName,toUnitsList,type);
     1193
     1194    fromIter = fromUnitsList.begin();
    11101195    toIter = toUnitsList.begin();
    11111196
    1112     // pass 1: compare basis' of objects to find intra-basis conversions
    11131197    while ( toIter != toUnitsList.end() ) {
    1114         rv = RpUnits::compareListEntryBasis(fromUnitsList, fromIter, toIter);
    1115         if (rv == 0) {
    1116 
    1117             // check the names of the units provided by the user
    1118             // if the names are the same, no need to do a conversion
    1119             if (fromIter->name() != toIter->name()) {
    1120 
    1121                 // do an intra-basis conversion
    1122                 toUnits = toIter->getUnitsObj();
    1123                 fromUnits = fromIter->getUnitsObj();
    1124 
    1125                 // do conversions
    1126                 factor = 1;
    1127                 factor = fromUnits->convert(toUnits, factor, &convResult);
    1128                 numVal *= pow(factor,toIter->getExponent());
    1129             }
    1130 
     1198        fromUnits = fromIter->getUnitsObj();
     1199        toUnits = toIter->getUnitsObj();
     1200
     1201        cList.clear();
     1202        convResult = fromUnits->getConvertFxnList(toUnits, cList);
     1203
     1204        if (convResult == 0) {
     1205
     1206            toExp = toIter->getExponent();
     1207            fromExp = fromIter->getExponent();
     1208
     1209            if (fromExp == toExp) {
     1210                copies = fromExp;
     1211                if (fromExp < 0) {
     1212                    copies = copies * -1.00;
     1213                    totalConvList.push_back(&invert);
     1214                }
     1215                while (copies > 0) {
     1216                    combineLists(totalConvList,cList);
     1217                    copies--;
     1218                }
     1219                if (fromExp < 0) {
     1220                    totalConvList.push_back(&invert);
     1221                }
     1222            }
     1223            else {
     1224                // currently we cannot handle conversions of
     1225                // units where the exponents are different
     1226                convResult++;
     1227            }
     1228
     1229        }
     1230
     1231        if (convResult == 0) {
     1232            // successful conversion reported
    11311233            // remove the elements from the lists
    11321234            tempIter = toIter;
    1133             toIter = toUnitsList.erase(tempIter);
    1134 //            toUnitsList.erase(tempIter);
    1135 //            toIter++;
     1235            toIter++;
     1236            toUnitsList.erase(tempIter);
    11361237
    11371238            tempIter = fromIter;
    11381239            fromUnitsList.erase(tempIter);
     1240            fromIter = fromUnitsList.begin();
    11391241        }
    11401242        else {
    1141             // this is not an intra-basis conversion.
    1142             // move onto the next toIter
    1143             toIter++;
    1144         }
    1145     }
    1146 
    1147     toIter = toUnitsList.begin();
    1148     fromIter = fromUnitsList.begin();
    1149 
    1150     // pass 2: look for inter-basis conversions
     1243            // no conversion available?
     1244            fromIter++;
     1245            if (fromIter == fromUnitsList.end()) {
     1246                fromIter = fromUnitsList.begin();
     1247                // raise error that there was an
     1248                // unrecognized conversion request
     1249                tempIter = toIter;
     1250                toIter++;
     1251                toUnitsList.erase(tempIter);
     1252            }
     1253        }
     1254
     1255    }
     1256
    11511257    if (fromIter != fromUnitsList.end()) {
    1152         // double while loop to compare each toIter with each fromIter.
    1153         // the outter while checks the toIter and the inner while
    1154         // which is conveniently hidden, adjusts the fromIter and toIter
    1155         // (at the bottom in the else statement).
    1156         while (toIter != toUnitsList.end()) {
    1157 
    1158             toUnits = toIter->getUnitsObj();
    1159             fromUnits = fromIter->getUnitsObj();
    1160 
    1161             // do an inter-basis conversion...the slow way
    1162             // there has to be a better way to do this...
    1163             convResult = 1;
    1164 
    1165             // in order to convert, exponents must be equal.
    1166             fromExp = fromIter->getExponent();
    1167             toExp   = toIter->getExponent();
    1168 
    1169             if (fromExp == toExp) {
    1170                 if (toExp == 1) {
    1171                     numVal = fromUnits->convert(toUnits, numVal, &convResult);
    1172                 }
    1173                 else {
    1174                     factor = 1;
    1175                     factor = fromUnits->convert(toUnits, factor, &convResult);
    1176                     numVal *= pow(factor,toExp);
    1177                 }
    1178             }
    1179 
    1180             if (convResult == 0) {
    1181                 // successful conversion reported
    1182                 // remove the elements from the lists
    1183                 tempIter = toIter;
    1184                 toUnitsList.erase(tempIter);
    1185                 toIter++;
    1186 
    1187                 tempIter = fromIter;
    1188                 fromUnitsList.erase(tempIter);
    1189 
    1190                 // conversion complete, jump out of the
    1191                 // while loop
    1192                 break;
    1193             }
    1194             else {
    1195                 // conversion was unsuccessful
    1196                 // move onto the next fromIter
    1197                 fromIter++;
    1198                 if (fromIter == fromUnitsList.end()) {
    1199                     // this is not an inter-basis conversion.
    1200                     // move onto the next toIter
    1201                     fromIter = fromUnitsList.begin();
    1202                     toIter++;
    1203                 }
    1204             } // end unsuccessful conversion
    1205         } // end toIter while loop
    1206     } // end
     1258        // raise error that there was an
     1259        // unrecognized conversion request
     1260    }
     1261
     1262
     1263    if (convResult == 0) {
     1264        convResult = applyConversion (&numVal, totalConvList);
     1265    }
    12071266
    12081267
     
    16231682
    16241683/**********************************************************************/
     1684// METHOD: getConvertFxnList()
     1685/// Return list of fxn pointers for converting two simple RpUnits objects.
     1686/**
     1687 * Return the conversion list that will convert from this RpUnits
     1688 * object to the provided toUnits object if the conversion is defined
     1689 * example
     1690 *      cm.getConvertFxnList(meter,cList)
     1691 *      cm.getConvertFxnList(angstrum,cList)
     1692 *
     1693 * Returns a list of conversion objects, represented by cList,
     1694 * on success that a value can be applied to. The return value
     1695 * will be zero (0).
     1696 * Returns non-zero value on failure.
     1697 */
     1698
     1699int
     1700RpUnits::getConvertFxnList(const RpUnits* toUnit, convertList& cList) const {
     1701
     1702    // currently we convert this object to its basis and look for the
     1703    // connection to the toUnit object from the basis.
     1704
     1705    const RpUnits* toBasis = toUnit->getBasis();
     1706    const RpUnits* fromUnit = this;
     1707    const RpUnits* dictToUnit = NULL;
     1708    convEntry *p;
     1709    int result = 0;
     1710
     1711    // guard against converting to the units you are converting from...
     1712    // ie. meters->meters
     1713    if (this->getUnitsName() == toUnit->getUnitsName()) {
     1714        return result;
     1715    }
     1716
     1717    // convert unit to the basis
     1718    // makeBasis(&value);
     1719    // trying to avoid the recursive way of converting to the basis.
     1720    // need to rethink this.
     1721    //
     1722    if ( (basis) && (basis->getUnitsName() != toUnit->getUnitsName()) ) {
     1723        result = fromUnit->getConvertFxnList(basis,cList);
     1724        if (result == 0) {
     1725            fromUnit = basis;
     1726        }
     1727        else {
     1728            // exit because an error occured while
     1729            // trying to convert to the basis
     1730            return result;
     1731        }
     1732    }
     1733
     1734    // find the toUnit in our dictionary.
     1735    // if the toUnits has a basis, we need to search for the basis
     1736    // and convert between basis' and then convert again back to the
     1737    // original unit.
     1738    if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
     1739        dictToUnit = find(toBasis->getUnitsName());
     1740    }
     1741    else {
     1742        dictToUnit = find(toUnit->getUnitsName());
     1743    }
     1744
     1745    // did we find the unit in the dictionary?
     1746    if (dictToUnit == NULL) {
     1747        // toUnit was not found in the dictionary
     1748        result = 1;
     1749        return result;
     1750    }
     1751
     1752    // search through the conversion list to find
     1753    // the conversion to the toUnit.
     1754
     1755    if (basis) {
     1756        p = basis->convList;
     1757    }
     1758    else {
     1759        p = this->convList;
     1760    }
     1761
     1762    if (p == NULL) {
     1763        // there are no conversions
     1764        result = 1;
     1765        return result;
     1766    }
     1767
     1768    // loop through our conversion list looking for the correct conversion
     1769    do {
     1770
     1771        if ( (p->conv->toPtr == dictToUnit) && (p->conv->fromPtr == fromUnit) ) {
     1772            // we found our conversion
     1773            // call the function pointer with value
     1774
     1775            // this should probably be re thought out
     1776            // the problem is that convForwFxnPtr has the conversion for a
     1777            // one arg conv function pointer and convForwFxnPtrDD has the
     1778            // conversion for a two arg conv function pointer
     1779            // need to make this simpler, more logical maybe only allow 2 arg
     1780            if (       (p->conv->convForwFxnPtr)
     1781                    && (! p->conv->convForwFxnPtrDD) ) {
     1782
     1783                // value = p->conv->convForwFxnPtr(value);
     1784                cList.push_back(p->conv->convForwFxnPtr);
     1785            }
     1786            /*
     1787            else if (  (p->conv->convForwFxnPtrDD)
     1788                    && (! p->conv->convForwFxnPtr) ) {
     1789
     1790                // value = p->conv->convForwFxnPtrDD(value, fromUnit->getExponent());
     1791                cList.pushback(conv);
     1792            }
     1793            */
     1794
     1795            // check to see if we converted to the actual requested unit
     1796            // or to the requested unit's basis.
     1797            // if we converted to the requested unit's basis. we need to
     1798            // do one last conversion from the requested unit's basis back
     1799            // to the requested unit.
     1800            if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
     1801                result += toBasis->getConvertFxnList(toUnit,cList);
     1802            }
     1803
     1804            break;
     1805        }
     1806
     1807        if ( (p->conv->toPtr == fromUnit) && (p->conv->fromPtr == dictToUnit) ) {
     1808            // we found our conversion
     1809            // call the function pointer with value
     1810
     1811            // this should probably be re thought out
     1812            // the problem is that convForwFxnPtr has the conversion for a
     1813            // one arg conv function pointer and convForwFxnPtrDD has the
     1814            // conversion for a two arg conv function pointer
     1815            // need to make this simpler, more logical maybe only allow 2 arg
     1816            if (       (p->conv->convBackFxnPtr)
     1817                    && (! p->conv->convBackFxnPtrDD) ) {
     1818
     1819                // value = p->conv->convBackFxnPtr(value);
     1820                cList.push_back(p->conv->convBackFxnPtr);
     1821            }
     1822            /*
     1823            else if (  (p->conv->convBackFxnPtrDD)
     1824                    && (! p->conv->convBackFxnPtr) ) {
     1825
     1826                // value = p->conv->convBackFxnPtrDD(value, fromUnit->getExponent());
     1827                cList.pushback(conv);
     1828            }
     1829            */
     1830
     1831            // check to see if we converted to the actual requested unit
     1832            // or to the requested unit's basis.
     1833            // if we converted to the requested unit's basis. we need to
     1834            // do one last conversion from the requested unit's basis back
     1835            // to the requested unit.
     1836            if ( (toBasis) && (toBasis->getUnitsName() != fromUnit->getUnitsName()) ) {
     1837                result += toBasis->getConvertFxnList(toUnit,cList);
     1838            }
     1839
     1840            break;
     1841        }
     1842
     1843        p = p->next;
     1844
     1845    } while (p != NULL);
     1846
     1847
     1848    if ( p == NULL) {
     1849        // we did not find the conversion
     1850        result += 1;
     1851    }
     1852
     1853    // return the converted value and result flag
     1854    return result;
     1855}
     1856
     1857/**********************************************************************/
     1858// METHOD: applyConversion()
     1859/// Apply a list of conversions in cList to the value val
     1860/**
     1861 * Apply a list of conversions, represented by cList, to the value
     1862 * val.
     1863 *
     1864 * Returns an integer value of zero (0) on success
     1865 * Returns non-zero value on failure.
     1866 */
     1867
     1868int
     1869RpUnits::applyConversion(double* val, convertList& cList) {
     1870
     1871    convertList::iterator iter;
     1872
     1873    if(val == NULL) {
     1874        return 1;
     1875    }
     1876
     1877    for(iter = cList.begin(); iter != cList.end(); iter++)
     1878    {
     1879        *val = (*iter)(*val);
     1880    }
     1881
     1882    return 0;
     1883}
     1884
     1885/**********************************************************************/
     1886// METHOD: combineLists()
     1887/// combine two convertLists in an orderly fasion
     1888/**
     1889 *
     1890 * elements of l2 are pushed onto l1 in the same order in which it
     1891 * exists in l2. l1 is changed in this function.
     1892 *
     1893 * Returns an integer value of zero (0) on success
     1894 * Returns non-zero value on failure.
     1895 */
     1896
     1897int
     1898RpUnits::combineLists(convertList& l1, convertList& l2) {
     1899
     1900    for (convertList::iterator iter = l2.begin(); iter != l2.end(); iter++) {
     1901        l1.push_back(*iter);
     1902    }
     1903    return 0;
     1904
     1905}
     1906
     1907/**********************************************************************/
     1908// METHOD: printList()
     1909/// print a list
     1910/**
     1911 *
     1912 * elements of l2 are pushed onto l1 in the same order in which it
     1913 * exists in l2. l1 is changed in this function.
     1914 *
     1915 * Returns an integer value of zero (0) on success
     1916 * Returns non-zero value on failure.
     1917 */
     1918
     1919int
     1920RpUnits::printList(convertList& l1) {
     1921
     1922    for (convertList::iterator iter = l1.begin(); iter != l1.end(); iter++) {
     1923        printf("%x\n", int((*iter)));
     1924    }
     1925    return 0;
     1926
     1927}
     1928
     1929/**********************************************************************/
    16251930// METHOD: insert()
    16261931/// Place an RpUnits Object into the Rappture Units Dictionary.
     
    16601965
    16611966        p->next = new convEntry (conv,p,NULL);
     1967    }
     1968
     1969}
     1970
     1971/**********************************************************************/
     1972// METHOD: connectIncarnation()
     1973/// Attach incarnation object information to a RpUnits Object.
     1974/**
     1975 */
     1976
     1977void
     1978RpUnits::connectIncarnation(const RpUnits* unit) const {
     1979
     1980    incarnationEntry* p = incarnationList;
     1981
     1982    if (p == NULL) {
     1983        incarnationList = new incarnationEntry (unit,NULL,NULL);
     1984    }
     1985    else {
     1986        while (p->next != NULL) {
     1987            p = p->next;
     1988        }
     1989
     1990        p->next = new incarnationEntry (unit,p,NULL);
    16621991    }
    16631992
     
    17292058    result += addPresetMass();
    17302059    result += addPresetPressure();
     2060    result += addPresetConcentration();
    17312061    result += addPresetMisc();
    17322062
     
    17962126    RpUnits::define(fahrenheit, kelvin, fahrenheit2kelvin, kelvin2fahrenheit);
    17972127    RpUnits::define(rankine, kelvin, rankine2kelvin, kelvin2rankine);
     2128    RpUnits::define(fahrenheit, rankine, fahrenheit2rankine, rankine2fahrenheit);
     2129    RpUnits::define(celcius, rankine, celcius2rankine, rankine2celcius);
    17982130
    17992131    return 0;
     
    18202152    RpUnits* angstrom   = RpUnits::define("A", NULL, RP_TYPE_LENGTH);
    18212153    RpUnits* inch       = RpUnits::define("in", NULL, RP_TYPE_LENGTH);
    1822     RpUnits* feet       = RpUnits::define("ft", NULL, RP_TYPE_LENGTH);
    1823     RpUnits* yard       = RpUnits::define("yd", NULL, RP_TYPE_LENGTH);
     2154    RpUnits* feet       = RpUnits::define("ft", inch, RP_TYPE_LENGTH);
     2155    RpUnits* yard       = RpUnits::define("yd", inch, RP_TYPE_LENGTH);
    18242156
    18252157    RpUnits::makeMetric(meters);
     
    18272159    // add length definitions
    18282160    RpUnits::define(angstrom, meters, angstrom2meter, meter2angstrom);
     2161    RpUnits::define(inch, feet, inch2feet, feet2inch);
     2162    RpUnits::define(inch, yard, inch2yard, yard2inch);
    18292163    RpUnits::define(inch, meters, inch2meter, meter2inch);
    1830     RpUnits::define(feet, meters, feet2meter, meter2feet);
    1831     RpUnits::define(yard, meters, yard2meter, meter2yard);
    18322164
    18332165    return 0;
     
    18392171/**
    18402172 * Defines the following units:
    1841  *   volt          (V)
    18422173 *   electron Volt (eV)
    18432174 *   joule         (J)
     
    18492180RpUnitsPreset::addPresetEnergy () {
    18502181
    1851     RpUnits* volt       = RpUnits::define("V", NULL, RP_TYPE_ENERGY);
    18522182    RpUnits* eVolt      = RpUnits::define("eV", NULL, RP_TYPE_ENERGY);
    18532183    RpUnits* joule      = RpUnits::define("J", NULL, RP_TYPE_ENERGY);
    18542184
    1855     RpUnits::makeMetric(volt);
    18562185    RpUnits::makeMetric(eVolt);
    18572186    RpUnits::makeMetric(joule);
     
    18702199 *   cubic feet (ft3)
    18712200 *   us gallons (gal)
     2201 *   liter      (L)
    18722202 *
    18732203 * Return codes: 0 success, anything else is error
     
    18772207RpUnitsPreset::addPresetVolume () {
    18782208
    1879     RpUnits* cubic_meter  = RpUnits::define("m3", NULL, RP_TYPE_VOLUME);
    1880     // RpUnits* pcubic_meter  = RpUnits::define("/m3", NULL, RP_TYPE_VOLUME);
    1881     RpUnits* cubic_feet   = RpUnits::define("ft3", NULL, RP_TYPE_VOLUME);
     2209    // RpUnits* cubic_meter  = RpUnits::define("m3", NULL, RP_TYPE_VOLUME);
     2210    // RpUnits* cubic_feet   = RpUnits::define("ft3", NULL, RP_TYPE_VOLUME);
    18822211    RpUnits* us_gallon    = RpUnits::define("gal", NULL, RP_TYPE_VOLUME);
    1883 
    1884     RpUnits::makeMetric(cubic_meter);
    1885 
    1886     // add energy definitions
    1887     RpUnits::define(cubic_meter,cubic_feet,meter2feet,feet2meter);
    1888     RpUnits::define(cubic_meter,us_gallon,cubicMeter2usGallon,usGallon2cubicMeter);
    1889     RpUnits::define(cubic_feet,us_gallon,cubicFeet2usGallon,usGallon2cubicFeet);
     2212    RpUnits* liter        = RpUnits::define("L", NULL, RP_TYPE_VOLUME);
     2213
     2214    /*
     2215    // RpUnits::makeMetric(cubic_meter);
     2216    const RpUnits* meter = NULL;
     2217    const RpUnits* foot = NULL;
     2218
     2219    meter = RpUnits::find("m");
     2220    if (meter && cubic_meter) {
     2221        RpUnits::incarnate(meter,cubic_meter);
     2222    }
     2223    else {
     2224        // raise an error, could not find meter unit
     2225    }
     2226
     2227    foot = RpUnits::find("ft");
     2228    if (foot && cubic_feet) {
     2229        RpUnits::incarnate(foot,cubic_feet);
     2230    }
     2231    else {
     2232        // raise an error, could not find meter unit
     2233    }
     2234    */
     2235
     2236    RpUnits::makeMetric(liter);
     2237
     2238
     2239    // add volume definitions
     2240    // RpUnits::define(cubic_meter,cubic_feet,meter2feet,feet2meter);
     2241    // RpUnits::define(cubic_meter,us_gallon,cubicMeter2usGallon,usGallon2cubicMeter);
     2242    // RpUnits::define(cubic_feet,us_gallon,cubicFeet2usGallon,usGallon2cubicFeet);
     2243    // RpUnits::define(cubic_meter,liter,cubicMeter2liter,liter2cubicMeter);
     2244    // RpUnits::define(liter,us_gallon,liter2us_gallon,us_gallon2liter);
    18902245
    18912246    return 0;
     
    19392294
    19402295    // add mass definitions
    1941     // RpUnits::define(radian,gradian,rad2grad,grad2rad);
    19422296
    19432297    return 0;
     
    19512305 *
    19522306 * Defines the following units:
     2307 *   atmosphere             (atm)
    19532308 *   bar                    (bar)
    19542309 *   pascal                 (Pa)
     
    19852340    RpUnits::define(torr,atmosphere,torr2atm,atm2torr);
    19862341    RpUnits::define(torr,psi,torr2psi,psi2torr);
     2342    RpUnits::define(atmosphere,psi,atm2psi,psi2atm);
    19872343
    19882344    RpUnits::define(torr,mmHg,torr2mmHg,mmHg2torr);
     2345
     2346    return 0;
     2347}
     2348
     2349/**********************************************************************/
     2350// METHOD: addPresetConcentration()
     2351/// Add concentration related units to the dictionary
     2352/**
     2353 * http://www.ilpi.com/msds/ref/pressureunits.html
     2354 *
     2355 * Defines the following units:
     2356 *   pH    (pH)
     2357 *   pOH    (pOH)
     2358 *
     2359 * Return codes: 0 success, anything else is error
     2360 */
     2361
     2362int
     2363RpUnitsPreset::addPresetConcentration () {
     2364
     2365    RpUnits* pH  = RpUnits::define("pH",  NULL, RP_TYPE_CONC);
     2366    RpUnits* pOH = RpUnits::define("pOH",  NULL, RP_TYPE_CONC);
     2367
     2368    // add concentration definitions
     2369    RpUnits::define(pH,pOH,pH2pOH,pOH2pH);
    19892370
    19902371    return 0;
     
    20042385RpUnitsPreset::addPresetMisc () {
    20052386
    2006     RpUnits* mole  = RpUnits::define("mol",  NULL, RP_TYPE_MISC);
    2007     RpUnits* hertz = RpUnits::define("Hz",  NULL, RP_TYPE_MISC);
     2387    RpUnits* volt      = RpUnits::define("V", NULL, RP_TYPE_ENERGY);
     2388    RpUnits* mole      = RpUnits::define("mol",  NULL, RP_TYPE_MISC);
     2389    RpUnits* hertz     = RpUnits::define("Hz",  NULL, RP_TYPE_MISC);
    20082390    RpUnits* becquerel = RpUnits::define("Bq",  NULL, RP_TYPE_MISC);
    20092391
     2392    RpUnits::makeMetric(volt);
    20102393    RpUnits::makeMetric(mole);
    20112394    RpUnits::makeMetric(hertz);
  • trunk/src/core/RpUnits.h

    r525 r534  
    3838#define RP_TYPE_MASS        "mass"
    3939#define RP_TYPE_PRESSURE    "pressure"
     40#define RP_TYPE_CONC        "concentration"
    4041#define RP_TYPE_MISC        "misc"
    4142
     
    6667        static int addPresetMass();
    6768        static int addPresetPressure();
     69        static int addPresetConcentration();
    6870        static int addPresetMisc();
    6971};
     
    229231};
    230232
     233// used by the RpUnits class to create a linked list of the incarnated units
     234// associated with the specific unit.
     235//
     236// we could templitize this and make a generic linked list
     237// or could use generic linked list class from book programming with objects
     238//
     239class incarnationEntry
     240{
     241
     242    public:
     243
     244        friend class RpUnits;
     245
     246        virtual ~incarnationEntry()
     247        {}
     248
     249    private:
     250
     251        const RpUnits* unit;
     252        incarnationEntry*  prev;
     253        incarnationEntry*  next;
     254
     255        incarnationEntry (
     256                const RpUnits* unit,
     257                incarnationEntry*  prev,
     258                incarnationEntry*  next
     259             )
     260            :   unit    (unit),
     261                prev    (prev),
     262                next    (next)
     263            {};
     264
     265};
     266
    231267class RpUnitsListEntry
    232268{
     
    324360                                int* result = NULL  ) const;
    325361
     362        static std::string convert1 ( std::string val,
     363                                     std::string toUnits,
     364                                     int showUnits,
     365                                     int* result = NULL );
     366
    326367        static std::string convert ( std::string val,
    327368                                     std::string toUnits,
     
    386427                                void* convBackData);
    387428
     429        static int incarnate (  const RpUnits* abstraction,
     430                                const RpUnits* entity);
    388431
    389432        // populate the dictionary with a set of units specified by group
    390         // if group equals......................then load................
    391         //      "all"                       load all available units
    392         //      "energy"                    load units related to energy
    393         //      "length"                    load units related to length
    394         //      "temp"                      load units related to temperature
    395         //      "time"                      load units related to time
    396         //      "volume"                    load units related to volume
    397         //      "angle"                     load units related to angles
     433        // if group equals........................then load................
     434        //                   "all"           load all available units
     435        //  RP_TYPE_ENERGY   "energy"        load units related to energy
     436        //  RP_TYPE_LENGTH   "length"        load units related to length
     437        //  RP_TYPE_TEMP     "temperature"   load units related to temperature
     438        //  RP_TYPE_TIME     "time"          load units related to time
     439        //  RP_TYPE_VOLUME   "volume"        load units related to volume
     440        //  RP_TYPE_ANGLE    "angle"         load units related to angles
     441        //  RP_TYPE_MASS     "mass"          load units related to mass
     442        //  RP_TYPE_PRESSURE "pressure"      load units related to pressure
     443        //  RP_TYPE_CONC     "concentration" load units related to pressure
     444        //  RP_TYPE_MISC     "misc"          load units related to everything else
    398445        //  (no other groups have been created)
    399446
     
    423470            convEntry* curr = NULL;
    424471
     472            incarnationEntry* r = NULL;
     473            incarnationEntry* rcurr = NULL;
     474
    425475            dict = other.dict;
    426476
     
    435485                }
    436486            }
     487
     488            if (other.incarnationList) {
     489                r = other.incarnationList;
     490                incarnationList = new incarnationEntry (r->unit,NULL,NULL);
     491                rcurr = incarnationList;
     492                while (r->next) {
     493                    r = r->next;
     494                    rcurr->next = new incarnationEntry (r->unit,rcurr,NULL);
     495                    rcurr = rcurr->next;
     496                }
     497            }
     498
    437499        }
    438500
     
    442504            convEntry* q = NULL;
    443505            convEntry* curr = NULL;
     506
     507            incarnationEntry* r = NULL;
     508            incarnationEntry* rcurr = NULL;
    444509
    445510            if ( this != &other ) {
     
    464529            }
    465530
     531            if (other.incarnationList) {
     532                r = other.incarnationList;
     533                incarnationList = new incarnationEntry (r->unit,NULL,NULL);
     534                rcurr = incarnationList;
     535                while (r->next) {
     536                    r = r->next;
     537                    rcurr->next = new incarnationEntry (r->unit,rcurr,NULL);
     538                    rcurr = rcurr->next;
     539                }
     540            }
     541
    466542            return *this;
    467543        }
     
    479555            convEntry* tmp = p;
    480556
     557            incarnationEntry* r = incarnationList;
     558            incarnationEntry* rtmp = r;
     559
    481560            while (p != NULL) {
    482561                tmp = p;
    483562                p = p->next;
    484563                delete tmp;
     564            }
     565
     566            while (p != NULL) {
     567                rtmp = r;
     568                r = r->next;
     569                delete rtmp;
    485570            }
    486571        }
     
    513598        mutable convEntry* convList;
    514599
     600        // linked list of incarnation units for this RpUnit
     601        // its mutable because the connectIncarnation function takes in a
     602        // const RpUnits* and attempts to change the incarnationList variable
     603        // within the RpUnits Object
     604        mutable incarnationEntry* incarnationList;
     605
    515606
    516607        // dictionary to store the units.
     
    535626                basis       (basis),
    536627                type        (type),
    537                 convList    (NULL)
     628                convList    (NULL),
     629                incarnationList (NULL)
    538630        {};
    539631
     
    544636
    545637        typedef std::list<LIST_TEMPLATE> RpUnitsList;
     638        typedef double (*convFxnPtrD) (double);
     639        typedef std::list<convFxnPtrD> convertList;
    546640        typedef RpUnitsList::iterator RpUnitsListIter;
    547641
     
    549643
    550644        static int units2list( const std::string& inUnits,
    551                                RpUnitsList& outList         );
     645                               RpUnitsList& outList,
     646                               std::string& type);
    552647        static int grabExponent(const std::string& inStr, double* exp);
    553648        static int grabUnitString( const std::string& inStr);
     
    565660
    566661        void RpUnits::connectConversion(conversion* conv) const;
     662        void RpUnits::connectIncarnation(const RpUnits* unit) const;
     663
     664        // return the conversion object that will convert
     665        // from this RpUnits to the proovided toUnits object
     666        // if the conversion is defined
     667        int getConvertFxnList (const RpUnits* toUnits, convertList& cList) const;
     668        static int applyConversion (double* val, convertList& cList);
     669        static int combineLists (convertList& l1, convertList& l2);
     670        static int printList (convertList& l1);
    567671
    568672};
  • trunk/src/core/RpUnitsStd.cc

    r525 r534  
    1414#endif
    1515
     16double invert (double inVal)
     17{
     18    return (1.0/inVal);
     19}
     20
    1621/****************************************
    1722 * METRIC CONVERSIONS
     
    1924
    2025
     26double deci2base (double deci)
     27{
     28   return deci*1e-1;
     29}
     30
    2131double centi2base (double centi)
    2232{
     
    5464}
    5565
     66double deca2base (double deca)
     67{
     68    return deca*1e1;
     69}
     70
     71double hecto2base (double hecto)
     72{
     73    return hecto*1e2;
     74}
     75
    5676double kilo2base (double kilo)
    5777{
     
    7999}
    80100
     101double exa2base (double exa)
     102{
     103    return exa*1e18;
     104}
     105
     106double base2deci (double base)
     107{
     108    return base*1e1;
     109}
     110
    81111double base2centi (double base)
    82112{
     
    114144}
    115145
     146double base2deca (double base)
     147{
     148    return base*1e-1;
     149}
     150
     151double base2hecto (double base)
     152{
     153    return base*1e-2;
     154}
     155
    116156double base2kilo (double base)
    117157{
     
    137177{
    138178    return base*1e-15;
     179}
     180
     181double base2exa (double base)
     182{
     183    return base*1e-18;
    139184}
    140185
     
    160205}
    161206
    162 double inch2meter (double in)
    163 {
    164     return (in/(39.37008));
    165 }
    166 
    167 double meter2feet (double meter)
    168 {
    169     return (meter*(3.280840));
    170 }
    171 
    172 double feet2meter (double ft)
    173 {
    174     return (ft/(3.280840));
    175 }
    176 
    177 double meter2yard (double meter)
    178 {
    179     return (meter*(1.093613));
    180 }
    181 
    182 double yard2meter (double yd)
    183 {
    184     return (yd/(1.093613));
     207double inch2meter (double inch)
     208{
     209    return (inch/(39.37008));
     210}
     211
     212double inch2feet (double inch)
     213{
     214    return (inch/(12.00));
     215}
     216
     217double feet2inch (double ft)
     218{
     219    return (ft*(12.00));
     220}
     221
     222double inch2yard (double inch)
     223{
     224    return (inch/(36.00));
     225}
     226
     227double yard2inch (double yd)
     228{
     229    return (yd*(36.00));
    185230}
    186231
     
    211256double rankine2kelvin (double R)
    212257{
    213     return ((9.0/5.0)*R);
     258    return ((5.0/9.0)*R);
    214259}
    215260
    216261double kelvin2rankine (double K)
    217262{
    218     return ((5.0/9.0)*K);
     263    return ((9.0/5.0)*K);
    219264}
    220265
     
    229274}
    230275
     276double fahrenheit2rankine (double F)
     277{
     278    return (F+459.67);
     279}
     280
     281double rankine2fahrenheit (double R)
     282{
     283    return (R-459.67);
     284}
     285
     286double rankine2celcius (double R)
     287{
     288    return ((R*(5.0/9.0))-273.15);
     289}
     290
     291double celcius2rankine (double C)
     292{
     293    return ((C + 273.15)*(9.0/5.0));
     294}
     295
    231296/****************************************
    232297 * ENERGY CONVERSIONS
     
    265330{
    266331    return (gal/7.48051);
     332}
     333
     334double cubicMeter2liter (double m3)
     335{
     336    return (m3*1e3);
     337}
     338
     339double liter2cubicMeter (double L)
     340{
     341    return (L*1e-3);
    267342}
    268343
     
    446521}
    447522
     523double psi2atm (double psi)
     524{
     525    return (psi*68.046e-3);
     526}
     527
     528double atm2psi (double atm)
     529{
     530    return (atm*14.696);
     531}
     532
     533/****************************************
     534 * CONCENTRATION CONVERSIONS
     535 * http://en.wikipedia.org/wiki/PH
     536 ****************************************/
     537
     538double pH2pOH (double pH)
     539{
     540    // This formula is valid exactly for
     541    // temperature = 298.15 K (25 °C) only,
     542    // but is acceptable for most lab calculations
     543    return (14.00 - pH);
     544}
     545
     546double pOH2pH (double pOH)
     547{
     548    // This formula is valid exactly for
     549    // temperature = 298.15 K (25 °C) only,
     550    // but is acceptable for most lab calculations
     551    return (14.00 - pOH);
     552}
    448553
    449554#ifdef __cplusplus
  • trunk/src/core/RpUnitsStd.h

    r525 r534  
    1212#endif
    1313
     14double invert (double inVal);
     15
     16double deci2base (double deci);
    1417double centi2base (double centi);
    1518double milli2base (double milli);
     
    1922double femto2base (double femto);
    2023double atto2base (double atto);
     24
     25double deca2base (double deca);
     26double hecto2base (double hecto);
    2127double kilo2base (double kilo);
    2228double mega2base (double mega);
     
    2430double tera2base (double tera);
    2531double peta2base (double peta);
     32double exa2base (double exa);
    2633
    2734
    2835
     36double base2deci (double base);
    2937double base2centi (double base);
    3038double base2milli (double base);
     
    3442double base2femto (double base);
    3543double base2atto (double base);
     44
     45double base2deca (double base);
     46double base2hecto (double base);
    3647double base2kilo (double base);
    3748double base2mega (double base);
     
    3950double base2tera (double base);
    4051double base2peta (double base);
     52double base2exa (double base);
    4153
    4254
     
    4557double meter2angstrom (double meter);
    4658double meter2inch (double meter);
    47 double inch2meter (double in);
    48 double meter2feet (double meter);
    49 double feet2meter (double ft);
    50 double meter2yard (double meter);
    51 double yard2meter (double yd);
     59double inch2meter (double inch);
     60double inch2feet (double inch);
     61double feet2inch (double ft);
     62double inch2yard (double inch);
     63double yard2inch (double yd);
    5264
    5365
     
    6274double fahrenheit2kelvin (double F);
    6375double kelvin2fahrenheit (double K);
     76double fahrenheit2rankine (double F);
     77double rankine2fahrenheit (double R);
     78double rankine2celcius (double R);
     79double celcius2rankine (double C);
    6480
    6581
     
    7591double cubicFeet2usGallon (double ft3);
    7692double usGallon2cubicFeet (double gal);
     93double cubicMeter2liter (double m3);
     94double liter2cubicMeter (double L);
    7795
    7896
     
    116134double torr2mmHg (double torr);
    117135double mmHg2torr (double mmHg);
    118 double kPa2KPa (double kPa);
    119 double KPa2kPa (double KPa);
     136double psi2atm (double psi);
     137double atm2psi (double atm);
    120138
    121139
     140
     141double pH2pOH (double pH);
     142double pOH2pH (double pOH);
    122143
    123144#ifdef __cplusplus
Note: See TracChangeset for help on using the changeset viewer.