Logo Search packages:      
Sourcecode: qbrew version File versions

quantity.cpp

/***************************************************************************
  quantity.h
  -------------------
  Generic quantity class
  -------------------
  Copyright 2001-2004, David Johnson
  Please see the header file for copyright and license information
 ***************************************************************************/

// version 0.1 (qt-ized)

#include <qtextstream.h>

#include "quantity.h"

// Unit Class ///////////////////////////////////////////////////////////////

// our static map units
QMap<QString,Unit*> Unit::units_;

/**
 * Full constructor. Construct a Unit from name and symbol
 * and add to map.
 */
00025 Unit::Unit(const QString &name, const QString &symbol)
    : name_(name), symbol_(symbol), conversions_()
{
    units_[symbol_] = this;
}

/**
 * Destructor. Removes Unit from map.
 */
00034 inline Unit::~Unit()
{
    units_.remove(symbol_);
}

/**
 * Add a conversion function for this Unit.
 */
00042 void Unit::addConversion(const Unit &u, const Conversion c)
{
    conversions_[u.name()] = c;
}

/**
 * Convert to amount of other units to this Unit.
 */
00050 double Unit::convert(double amount, const Unit &other) const
{
    // if converting from self...
    if (other.name_ == name_) return amount;
    
    if (convertable(other)) {
        return (*conversions_.find(other.name()))(amount);
    }
    // TODO: throw exception instead of returning 0.0
    return 0.0;
}

/**
 * Return Unit associated with symbol.
 */
00065 Unit* Unit::unit(const QString &symbol)
{
    if (units_.find(symbol) != units_.end())
        return units_.find(symbol).data();
    else
        return 0;
}

// Quantity Class ///////////////////////////////////////////////////////////

Unit Quantity::generic("unit", "unit");

/**
 * Assignment operator.
 */
00080 Quantity &Quantity::operator=(const Quantity &q)
{
    if (this != &q) {
        amount_ = q.amount_;
        unit_ = q.unit_;
    }
    return *this;
}

/**
 * Equivalence operator.
 */
00092 bool Quantity::operator==(const Quantity &q) const
{
    return ((amount_ == q.amount_) &&
            (unit_->symbol() == q.unit_->symbol()));
}

/**
 * Convert Quanity to unit.
 */
00101 void Quantity::convert(const Unit &u)
{
    amount_ = unit_->convert(amount_, u);
    unit_ = &u;
    // TODO: change to bool return, and return false if not convertable
}

/**
 * Output quantity as a string, output is "xx.xx symbol".
 */
00111 QString Quantity::toQString()
{
    return (QString::number(amount_, 'f') + " " + unit_->symbol());
}

/**
 * Set quantity from string
 */
00119 void Quantity::fromQString(const QString &from, const Unit &defaultunit)
{
    double d;
    QString s;
    QTextStream istr(const_cast<QString*>(&from), IO_ReadOnly );
    
    istr >> d;
    istr.skipWhiteSpace();
    s = istr.readLine();

    Unit* u = Unit::unit(s);
    amount_ = d;
    if (u) unit_ = u;
    else unit_ = &defaultunit;
}

// Addition operators /////////////////

Quantity &Quantity::operator+=(const Quantity &q)
{
    if (unit_->convertable(*q.unit_)) {
        amount_ += q.unit_->convert(q.amount_, *unit_);
    }
    return *this;
}

Quantity operator+(const Quantity &q1, const Quantity &q2)
{
    Quantity temp(q1);
    if (temp.unit_->convertable(*q2.unit_)) {
        temp.amount_ += q2.unit_->convert(q2.amount_, *temp.unit_);
    }
    return temp;
}

Quantity operator+(const Quantity &q, const double d)
{
    Quantity temp(q);
    temp.amount_ += d;
    return temp;
}

// Subtraction operators //////////////

Quantity &Quantity::operator-=(const Quantity &q)
{
    if (unit_->convertable(*q.unit_)) {
        amount_ -= q.unit_->convert(q.amount_, *unit_);
    }
    return *this;
}

Quantity operator-(const Quantity &q1, const Quantity &q2)
{
    Quantity temp(q1);
    if (temp.unit_->convertable(*q2.unit_)) {
        temp.amount_ += q2.unit_->convert(q2.amount_, *temp.unit_);
    }
    return temp;
}

Quantity operator-(const Quantity &q, const double d)
{
    Quantity temp(q);
    temp.amount_ -= d;
    return temp;
}

Quantity operator-(const double d, const Quantity &q)
{
    Quantity temp(q);
    temp.amount_ = d - temp.amount_;
    return temp;
}

// Multiplication operators ///////////

Quantity operator*(const Quantity &q, const double d)
{
    Quantity temp(q);
    temp.amount_ *= d;
    return temp;
}

// Division operators /////////////////

// TODO: should throw if div by zero
Quantity operator/(const Quantity &q, const double d)
{
    Quantity temp(q);
    temp.amount_ /= d;
    return temp;
}

Quantity operator/(const double d, const Quantity &q)
{
    Quantity temp(q);
    temp.amount_ = d / temp.amount_;
    return temp;
}

// Misc operators /////////////////////

Quantity operator-(const Quantity &q)
{
    Quantity temp(q);
    temp.amount_ *= -1.0;
    return temp;
}

// Weight Class //////////////////////////////////////////////////////////

Unit Weight::gram("gram", "g");
Unit Weight::kilogram("kilogram", "kg");
Unit Weight::ounce("ounce", "oz");
Unit Weight::pound("pound", "lb");

bool Weight::initialized_ = false;

/**
 * Constructor.
 */
Weight::Weight(double amount, const Unit &unit) 
    : Quantity(amount, unit)
{
    if (!initialized_) initialize();
}

/**
 * Conversion constructor. Converts from base Quantity.
 */
Weight::Weight(const Quantity &q)
    : Quantity(q)
{
    if (!initialized_) initialize();
    // TODO: throw if nonconvertable
}

/**
 * Initialize the class units.
 */
void Weight::initialize()
{
    gram.addConversion(kilogram, gram2kilogram);
    gram.addConversion(ounce, gram2ounce);
    gram.addConversion(pound, gram2pound);
    kilogram.addConversion(gram, kilogram2gram);
    kilogram.addConversion(ounce, kilogram2ounce);
    kilogram.addConversion(pound, kilogram2pound);
    ounce.addConversion(gram, ounce2gram);
    ounce.addConversion(kilogram, ounce2kilogram);
    ounce.addConversion(pound, ounce2pound);
    pound.addConversion(gram, pound2gram);
    pound.addConversion(kilogram, pound2kilogram);
    pound.addConversion(ounce, pound2ounce);
    initialized_ = true;
}

// Volume Class //////////////////////////////////////////////////////////

Unit Volume::barrel("barrel", "bbl");
Unit Volume::gallon("gallon", "gal");
Unit Volume::hectoliter("hectoliter", "hL");
Unit Volume::liter("liter", "L");
Unit Volume::milliliter("milliliter", "mL");
Unit Volume::fluidounce("fluid ounce", "fl oz");

bool Volume::initialized_ = false;

/**
 * Constructor.
 */
Volume::Volume(double amount, const Unit &unit) 
    : Quantity(amount, unit)
{
    if (!initialized_) initialize();
}

/**
 * Conversion constructor. Converts from base Quantity.
 */
Volume::Volume(const Quantity &q)
    : Quantity(q)
{
    if (!initialized_) initialize();
    // TODO: throw if nonconvertable
}

/**
 * Initialize the class units.
 */
void Volume::initialize()
{
    barrel.addConversion(fluidounce, barrel2fluidounce);
    barrel.addConversion(gallon, barrel2gallon);
    barrel.addConversion(hectoliter, barrel2hectoliter);
    barrel.addConversion(liter, barrel2liter);
    barrel.addConversion(milliliter, barrel2milliliter);
    fluidounce.addConversion(barrel, fluidounce2barrel);
    fluidounce.addConversion(gallon, fluidounce2gallon);
    fluidounce.addConversion(hectoliter, fluidounce2hectoliter);
    fluidounce.addConversion(liter, fluidounce2liter);
    fluidounce.addConversion(milliliter, fluidounce2milliliter);
    gallon.addConversion(barrel, gallon2barrel);
    gallon.addConversion(fluidounce, gallon2fluidounce);
    gallon.addConversion(hectoliter, gallon2hectoliter);
    gallon.addConversion(liter, gallon2liter);
    gallon.addConversion(milliliter, gallon2milliliter);
    hectoliter.addConversion(barrel, hectoliter2barrel);
    hectoliter.addConversion(fluidounce, hectoliter2fluidounce);
    hectoliter.addConversion(gallon, hectoliter2gallon);
    hectoliter.addConversion(liter, hectoliter2liter);
    hectoliter.addConversion(milliliter, hectoliter2milliliter);
    liter.addConversion(barrel, liter2barrel);
    liter.addConversion(fluidounce, liter2fluidounce);
    liter.addConversion(gallon, liter2gallon);
    liter.addConversion(hectoliter, liter2hectoliter);
    liter.addConversion(milliliter, liter2milliliter);
    milliliter.addConversion(barrel, milliliter2barrel);
    milliliter.addConversion(fluidounce, milliliter2fluidounce);
    milliliter.addConversion(gallon, milliliter2gallon);
    milliliter.addConversion(hectoliter, milliliter2hectoliter);
    milliliter.addConversion(liter, milliliter2liter);
    initialized_ = true;
}

// Conversion Functions //////////////////////////////////////////////////

// TODO: double check formulas

double gram2kilogram(double value)
    { return value / 1000.0; }

double gram2ounce(double value)
    { return value / 28.349523125; }

double gram2pound(double value)
    { return value / 453.59237; }

double kilogram2gram(double value)
    { return value * 1000.0 ; }

double kilogram2ounce(double value)
    { return value * 35.27396; }

double kilogram2pound(double value)
    { return value * 2.2046226; }

double ounce2gram(double value)
    { return value * 28.349523125; }

double ounce2kilogram(double value)
    { return value / 35.27396; }

double ounce2pound(double value)
    { return value / 16.0; }

double pound2gram(double value)
    { return value * 453.59237; }

double pound2kilogram(double value)
    { return value / 2.2046226; }

double pound2ounce(double value)
    { return value * 16.0; }

double barrel2fluidounce(double value)
    { return value * 3968.0; }

double barrel2gallon(double value)
    { return value * 31.0; }

double barrel2hectoliter(double value)
    { return value * 1.173477658; }

double barrel2liter(double value)
    { return value * 117.3477658; }

double barrel2milliliter(double value)
    { return value * 117347.7658; }

double fluidounce2barrel(double value)
    { return value / 3968.0; }

double fluidounce2gallon(double value)
    { return value / 128.0; }

double fluidounce2hectoliter(double value)
    { return value / 3381.4016; }

double fluidounce2liter(double value)
    { return value / 33.814016; }

double fluidounce2milliliter(double value)
    { return value * 29.5735; }

double gallon2barrel(double value)
    { return value / 31.0; }

double gallon2fluidounce(double value)
    { return value * 128.0; }

double gallon2hectoliter(double value)
    { return value / 26.4172; }

double gallon2liter(double value)
    { return value * 3.7854118; }

double gallon2milliliter(double value)
    { return value * 3785.4118; }

double hectoliter2barrel(double value)
    { return value / 1.173477658; }

double hectoliter2fluidounce(double value)
    { return value * 3381.4016; }

double hectoliter2gallon(double value)
    { return value * 26.4172; }

double hectoliter2liter(double value)
    { return value * 100.0; }

double hectoliter2milliliter(double value)
    { return value * 100000.0; }

double liter2barrel(double value)
    { return value / 117.3477658; }

double liter2fluidounce(double value)
    { return value * 33.814016; }

double liter2gallon(double value)
    { return value / 3.7854118; }

double liter2hectoliter(double value)
    { return value / 100.0; }

double liter2milliliter(double value)
    { return value * 1000.0; }

double milliliter2barrel(double value)
    { return value / 117347.7658; }

double milliliter2fluidounce(double value)
    { return value / 29.5735; }

double milliliter2gallon(double value)
    { return value / 3785.4118; }

double milliliter2hectoliter(double value)
    { return value / 100000.0; }

double milliliter2liter(double value)
    { return value / 1000.0; }

Generated by  Doxygen 1.6.0   Back to index