Ejemplo n.º 1
0
  std::string Unit_Impl::prettyString(bool withScale) const {

    if (withScale && !m_prettyString.empty() && (scale().exponent != 0)) {
      Unit wUnit = parseUnitString(m_prettyString);
      wUnit.setScale(scale().exponent);
      return wUnit.standardString(withScale);
    }

    return m_prettyString;
  }
Ejemplo n.º 2
0
  void Unit_Impl::pow(int expNum, int expDenom, bool okToCallFactory) {
    std::vector<UnitElement>::iterator unitsIter;
    std::vector<UnitElement>::iterator unitsEnd = m_units.end();

    // check for errors first
    if (expDenom != 1) {
      // baseUnit exponents ok in integer arithmetic?
      for (unitsIter = m_units.begin(); unitsIter != unitsEnd; ++unitsIter) {
        if ((unitsIter->second * expNum) % expDenom != 0) {
          LOG_AND_THROW("Unit raised to fractional power " << expNum << "/" << expDenom
                        << " that resulted in non-integer exponent on baseUnit " << unitsIter->first);
        }
      }

      // scale exponent ok in integer arithmetic?
      if ((scale().exponent * expNum) % expDenom != 0) {
        LOG_AND_THROW("Scale " << scale().name << " cannot be raised to the power "
                      << expNum << "/" << expDenom << " since that results in a fractional exponent.");
      }
    }

    // baseUnit exponents
    for (unitsIter = m_units.begin(); unitsIter != unitsEnd; ++unitsIter) {
      unitsIter->second *= expNum;
      unitsIter->second /= expDenom;
    }

    // scale
    if (scale().exponent != 0) {
      ScaleOpReturnType resultScale = openstudio::pow(scale(),expNum,expDenom);
      setScale(resultScale.first().exponent);
    }

    // pretty string
    std::string stdStr = standardString(false);

    std::string prettyStringFromFactory;
    if (okToCallFactory){
      prettyStringFromFactory = UnitFactory::instance().lookupPrettyString(stdStr);
    }
    if (prettyStringFromFactory != "") {
      setPrettyString(prettyStringFromFactory);
    }
    else {
      // otherwise handle
      if (prettyString(false) != "") {
        Unit wThisPretty = parseUnitString(prettyString(false));
        wThisPretty.pow(expNum,expDenom,okToCallFactory);
        setPrettyString(wThisPretty.standardString(false));
      }
    } // if
  }
Ejemplo n.º 3
0
IddUnitString::IddUnitString (const std::string &s)
    : m_original(s), m_converted(s)
{
    // remove differentiation between kg-H2O and kg-Air (will be kg/kg).
    // better to add kg-H2O and kg-air as separate SI base units?
    m_converted = boost::regex_replace(m_converted,boost::regex("-H2O"),"");
    m_converted = boost::regex_replace(m_converted,boost::regex("-[aA]ir"),"");
    m_converted = boost::regex_replace(m_converted,boost::regex("Water"),"");
    m_converted = boost::regex_replace(m_converted,boost::regex("DryAir"),"");

    // basic replacements
    m_converted = boost::regex_replace(m_converted,boost::regex("-"),"*");
    if (!boost::regex_search(m_converted,boost::regex("H2O"))) {
        m_converted = boost::regex_replace(m_converted,boost::regex("([2-9]+)"),"^\\1");
    }
    else {
        m_converted = boost::regex_replace(m_converted,boost::regex("H2O"),"H_{2}O");
    }
    m_converted = boost::regex_replace(m_converted,boost::regex("deltaC"),"K");
    m_converted = boost::regex_replace(m_converted,boost::regex("minutes"),"min");
    m_converted = boost::regex_replace(m_converted,boost::regex("dimensionless"),"");
    m_converted = boost::regex_replace(m_converted,boost::regex("Person"),"person");
    m_converted = boost::regex_replace(m_converted,boost::regex("Rotations Per Minute"),"rpm");
    m_converted = boost::regex_replace(m_converted,boost::regex("ohms"),"ohm");
    m_converted = boost::regex_replace(m_converted,boost::regex("VA"),"V*A");
    m_converted = boost::regex_replace(m_converted,boost::regex("deltaJ"),"J");
    m_converted = boost::regex_replace(m_converted,boost::regex("rev"),"cycle");
    m_converted = boost::regex_replace(m_converted,boost::regex("Ah"),"A*h");

    // relative temperatures
    if (!boost::regex_match(m_converted,boost::regex("C|F"))) {
        m_converted = boost::regex_replace(m_converted,boost::regex("C"),"K");
        m_converted = boost::regex_replace(m_converted,boost::regex("F"),"R");
    }

    // Multiple /'s
    boost::smatch matches;
    if (boost::regex_match(m_converted,matches,boost::regex("(.*)/\\((.*)/(.*)\\)"))) {
        std::string part1(matches[1].first, matches[1].second);
        std::string part2(matches[2].first, matches[2].second);
        std::string part3(matches[3].first, matches[3].second);
        m_converted = part1 + "*" + part3 + "/" + part2;
    }

    if (boost::regex_match(m_converted,matches,boost::regex("\\((.*)/(.*)\\)/(.*)"))) {
        std::string part1(matches[1].first, matches[1].second);
        std::string part2(matches[2].first, matches[2].second);
        std::string part3(matches[3].first, matches[3].second);
        m_converted = part1 + "/" + part2 + "*" + part3;
    }

    if ((!m_converted.empty()) && boost::regex_search(m_converted,boost::regex("g"))) {
        Unit temp = parseUnitString(m_converted);

        // g -> m(kg)
        int gExp = temp.baseUnitExponent("g");
        if (gExp != 0) {
            temp.setBaseUnitExponent("g",0);
            temp.setBaseUnitExponent("kg",gExp);
            bool ok = temp.setScale(-3 * gExp);
            if (ok) {
                m_converted = temp.standardString();
            }
        }
    }

    if ((!m_converted.empty()) && boost::regex_search(m_converted,boost::regex("micron"))) {
        Unit temp = parseUnitString(m_converted);

        int gExp = temp.baseUnitExponent("micron");
        if (gExp != 0) {
            temp.setBaseUnitExponent("micron",0);
            temp.setBaseUnitExponent("m",gExp);
            bool ok = temp.setScale(-6 * gExp);
            if (ok) {
                m_converted = temp.standardString();
            }
        }
    }
}
Ejemplo n.º 4
0
boost::optional<Quantity> QuantityConverterSingleton::m_convertToTargetFromSI(
    const Quantity& original,const Unit& targetUnits) const
{
  Quantity working(original);

  // Make sure to work unscaled: 10^0
  if (working.scale().exponent != 0) {
    working.setScale(0);
  }
  Quantity converted(working.value(),targetUnits.system());

  if ((working.units() == targetUnits) &&
      (working.system() == targetUnits.system()))
  {
    converted = working;
  }
  else {
    // Get the base units of targetUnits
    std::vector<std::string> baseOfTarget = targetUnits.baseUnits();
    // Loop over base units in original and apply (inverse of) conversions in m_toSImap
    std::vector<std::string>::const_iterator it = baseOfTarget.begin();
    std::vector<std::string>::const_iterator end = baseOfTarget.end();
    while( it != end ) {
      int baseExponent = targetUnits.baseUnitExponent(*it);
      // apply conversion factor
      BaseUnitConversionMap::const_iterator mapItr = m_toSImap.find(*it);
      if (mapItr == m_toSImap.end()) {
        LOG(Error,"Cannot convert to a target Unit containing base unit '" << *it
            << "', because it is not registered with the QuantityConverter.");
        return boost::none;
      }
      baseUnitConversionFactor factor = m_toSImap.find(*it)->second;
      if (factor.offset != 0.0) {
        for( int i = 0; i < std::abs(baseExponent); ++i) {
          if( baseExponent > 0 ){
            converted.setValue( (converted.value() - factor.offset) / factor.factor);
          }else {
            converted.setValue( (converted.value() - factor.offset) * factor.factor);
          }
        }
      }
      else {
        converted.setValue( converted.value() * std::pow(factor.factor,-baseExponent) );
      }
      // Set units in converted
      converted.setBaseUnitExponent(*it,
                                    converted.baseUnitExponent(*it) + baseExponent);
      // Monitor left over units in working
      // Parse the conversion string in case the target converts to more than one SI base unit
      Unit sourceBase = parseUnitString(factor.targetUnit);
      std::vector<std::string> sourceStrings = sourceBase.baseUnits();
      std::vector<std::string>::const_iterator sourceItr = sourceStrings.begin();
      std::vector<std::string>::const_iterator sourceEnd = sourceStrings.end();
      while( sourceItr != sourceEnd ) {
        int exp = sourceBase.baseUnitExponent( *sourceItr );
        if( exp != 0 ) {
          working.setBaseUnitExponent(*sourceItr,
                                      working.baseUnitExponent(*sourceItr) - baseExponent*exp);
        }
        ++sourceItr;
      } // end while( sourceItr != sourceEnd )
      ++it;
    }

    if (!working.standardUnitsString().empty()) {
      LOG(Error,"Could not convert " << original << " to " << targetUnits
          << ". Have " << working.standardUnitsString() << "left over.");
      return boost::none;
    }
  }

  // Set result scale to match targetUnits scale
  if (targetUnits.scale().exponent != 0) {
    converted.setScale(targetUnits.scale().exponent);
  }

  // Check if there is a pretty string for the result
  std::string pretty = UnitFactory::instance().lookupPrettyString(
    converted.standardUnitsString(false) );
  if( !(pretty.empty()) ) {
    converted.setPrettyUnitsString( pretty );
  }

  return converted;
}
Ejemplo n.º 5
0
Quantity QuantityConverterSingleton::m_convertFromSI(const Quantity &original,
                                                     const UnitSystem targetSys) const
{
  Quantity working(original);

  // Make sure to work unscaled: 10^0
  int scaleExponent = working.scale().exponent;
  if (working.scale().exponent != 0) {
    working.setScale(0);
  }
  Quantity converted(working.value(),targetSys);

  UnitSystemConversionMultiMap::const_iterator factorItr;
  // m_fromSImap is a multi-map, so get the range of values that match the key 'targetSys'
  std::pair<UnitSystemConversionMultiMap::const_iterator, UnitSystemConversionMultiMap::const_iterator> systemFactors;
  systemFactors = m_fromSIBySystemMap.equal_range( targetSys );
  for( factorItr = systemFactors.first; factorItr != systemFactors.second; ++factorItr) {
    baseUnitConversionFactor fromFactor = (*factorItr).second;
    int workingExp = working.baseUnitExponent(fromFactor.originalUnit);
    if (fromFactor.offset != 0.0) {
      for( int i=0; i < std::abs(workingExp); ++i ) {
        if( workingExp > 0 ) {
          converted.setValue( (converted.value() * fromFactor.factor) + fromFactor.offset );
        }
        else {
          converted.setValue( (converted.value() / fromFactor.factor) + fromFactor.offset );
        }
      }
    }
    else {
      converted.setValue(converted.value() * std::pow(fromFactor.factor,workingExp) );
    }
    // Parse the conversion string incase the SI unit converts to more than one target base unit
    Unit targetBase = parseUnitString(fromFactor.targetUnit);
    std::vector<std::string> targetStrings = targetBase.baseUnits();
    std::vector<std::string>::const_iterator targetItr = targetStrings.begin();
    std::vector<std::string>::const_iterator targetEnd = targetStrings.end();
    while( targetItr != targetEnd ) {
      int exp = targetBase.baseUnitExponent( *targetItr );
      if( exp != 0) {
        converted.setBaseUnitExponent(*targetItr,converted.baseUnitExponent(*targetItr) + 
                                                 workingExp*exp);
      }
      ++targetItr;
    }//End while( convItr != targetEnd )
  }

  // Set result scale to match original scale
  if( scaleExponent != 0 ) {
    converted.setScale(scaleExponent);
  }

  // Check if there is a pretty string for the result
  std::string pretty = UnitFactory::instance().lookupPrettyString(
    converted.standardUnitsString(false) );
  if( !(pretty.empty()) ) {
    converted.setPrettyUnitsString( pretty );
  }

  return converted;
}
Ejemplo n.º 6
0
boost::optional<Quantity> QuantityConverterSingleton::m_convertToSI(const Quantity &original) const
{
  // create a working copy of the original
  Quantity working(original);
  // Make sure to work unscaled: 10^0
  int scaleExponent = working.scale().exponent;
  if (working.scale().exponent != 0) {
    working.setScale(0);
  }
  // build a result quantity with SI units and value equal to original
  Quantity result(working.value(), UnitSystem(UnitSystem::SI));

  // Get the base units of original
  std::vector<std::string> baseOfOriginal = original.baseUnits();
  // Loop over base units in original and apply conversions found in m_toSImap
  std::vector<std::string>::const_iterator it = baseOfOriginal.begin();
  std::vector<std::string>::const_iterator end = baseOfOriginal.end();
  while( it != end ) {
    int baseExponent = working.baseUnitExponent(*it);
    // apply conversion factor
    BaseUnitConversionMap::const_iterator mapItr = m_toSImap.find(*it);
    if (mapItr == m_toSImap.end()) {
      LOG(Error,"Cannot convert base unit '" << *it << "' to SI because it is not "
          << "registered with the QuantityConverter.");
      return boost::none;
    }
    baseUnitConversionFactor factor = mapItr->second;
    if (factor.offset != 0.0) {
      for( int i = 0; i < std::abs(baseExponent); ++i) {
        if( baseExponent > 0 ){
          result.setValue( (result.value() * factor.factor) + factor.offset);
        }else {
          result.setValue( (result.value() / factor.factor) + factor.offset);
        }
      }
    }
    else {
      result.setValue( result.value() * std::pow(factor.factor,baseExponent) );
    }
    // Parse the conversion string in case the original converts to more than one SI base unit
    Unit targetBase = parseUnitString(factor.targetUnit);
    std::vector<std::string> targetStrings = targetBase.baseUnits();
    std::vector<std::string>::const_iterator targetItr = targetStrings.begin();
    std::vector<std::string>::const_iterator targetEnd = targetStrings.end();
    while( targetItr != targetEnd ) {
      int exp = targetBase.baseUnitExponent( *targetItr );
      if( exp != 0 ) {
        result.setBaseUnitExponent(*targetItr,result.baseUnitExponent(*targetItr) + 
                                              baseExponent*exp);
      }
      ++targetItr;
    }//End while( convItr != convEnd )
    ++it;
  }//End while( it != end )

  // Set result scale to match original scale
  if( scaleExponent != 0 ) {
    result.setScale(scaleExponent);
  }

  // Check if there is a pretty string for the result
  std::string pretty = UnitFactory::instance().lookupPrettyString( 
    result.standardUnitsString(false) );
  if( !(pretty.empty()) ) {
    result.setPrettyUnitsString( pretty );
  }

  return result;
}
Ejemplo n.º 7
0
  void Unit_Impl::operator*=(const Unit& rUnit) {

    if ((m_system != rUnit.system()) && (m_system != UnitSystem::Mixed)) {
      LOG_AND_THROW("Cannot " << m_system.valueName() << " *= " << rUnit.system().valueName()
                    << ". Must have same systems, or UnitSystem::Mixed on the left-hand side.");
    }

    if (this == rUnit.getImpl<Unit_Impl>().get()) {
      // u1 * u1
      this->pow(2);
      return;
    }

    // u1 * u2, loop through both
    std::vector<UnitElement>::iterator lUnitsIter;
    std::vector<UnitElement>::iterator lUnitsEnd = m_units.end();
    std::vector<UnitElement>::const_iterator rUnitsIter;
    std::vector<UnitElement>::const_iterator rUnitsEnd = rUnit.getImpl<detail::Unit_Impl>()->m_units.end();
    bool ordered = true;
    for (lUnitsIter = m_units.begin(), rUnitsIter = rUnit.getImpl<detail::Unit_Impl>()->m_units.begin();
    (lUnitsIter != lUnitsEnd) && (rUnitsIter != rUnitsEnd);
    ++lUnitsIter, ++rUnitsIter) {
      if (lUnitsIter->first != rUnitsIter->first) {
        // different order
        ordered = false;
        break;
      }
      else {
        lUnitsIter->second += rUnitsIter->second;
      }
    }

    if (ordered && (rUnitsIter != rUnitsEnd)) {
      // finish looping through rUnits and append any non-zero exponented baseUnits
      for (; rUnitsIter != rUnitsEnd; ++rUnitsIter) {
        if (rUnitsIter->second != 0) {
          setBaseUnitExponent(rUnitsIter->first,rUnitsIter->second);
        }
      }
    }
    else if (!ordered) {
      // mark baseUnits as checked
      std::vector<std::string> checkedBaseUnits;
      std::vector<UnitElement>::const_iterator tmpLUnitsIter;
      for (tmpLUnitsIter = m_units.begin(); tmpLUnitsIter != lUnitsIter; ++tmpLUnitsIter) {
        checkedBaseUnits.push_back(tmpLUnitsIter->first);
      }
      // pick up with lUnits
      for (; lUnitsIter != lUnitsEnd; ++lUnitsIter) {
        rUnitsIter = rUnit.getImpl<detail::Unit_Impl>()->findBaseUnit(lUnitsIter->first);
        if (rUnitsIter != rUnitsEnd) {
          lUnitsIter->second += rUnitsIter->second;
          checkedBaseUnits.push_back(lUnitsIter->first);
        }
      }
      // check rUnits
      std::vector<std::string>::iterator checkedBaseUnitsEnd = checkedBaseUnits.end();
      for (rUnitsIter = rUnit.getImpl<detail::Unit_Impl>()->m_units.begin();
      rUnitsIter != rUnitsEnd; ++rUnitsIter)
      {
        std::vector<std::string>::iterator loc =
            std::find(checkedBaseUnits.begin(),checkedBaseUnitsEnd,rUnitsIter->first);
        if (loc == checkedBaseUnitsEnd) {
          // this base unit not checked yet, and is not in lUnits
          if (rUnitsIter->second != 0) {
            setBaseUnitExponent(rUnitsIter->first,rUnitsIter->second);
          }
        } // if
      } // for
    }

    ScaleOpReturnType resultScale = scale()*rUnit.scale();
    setScale(resultScale.first().exponent);

    std::string prettyStringFromFactory = UnitFactory::instance().lookupPrettyString(standardString(false));
    if (prettyStringFromFactory != "") {
      setPrettyString(prettyStringFromFactory);
    }
    else {
      // otherwise need to handle pretty string
      if (prettyString(false) != "") {
        Unit wThisPretty = parseUnitString(prettyString(false));
        if (rUnit.prettyString(false) != "") {
          Unit wRUnitPretty = parseUnitString(rUnit.prettyString(false));
          wThisPretty *= wRUnitPretty;
        }
        else {
          wThisPretty *= rUnit;
        }
        setPrettyString(wThisPretty.standardString(false));
      }
    }
  }