Use typesafe enum classes in pv::util
authorJens Steinhauser <jens.steinhauser@gmail.com>
Sun, 30 Aug 2015 21:20:21 +0000 (23:20 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Fri, 4 Sep 2015 10:54:52 +0000 (12:54 +0200)
pv/util.cpp
pv/util.hpp
pv/view/cursorpair.cpp
pv/view/view.cpp
pv/view/view.hpp
pv/widgets/timestampspinbox.cpp
test/util.cpp

index cf2d7f90bfcf9761eb4cef4a6b5eb38a7e2c43e3..7bf6f434a39a519c9e34d3da08e7de36c3177db2 100644 (file)
@@ -35,16 +35,40 @@ using namespace Qt;
 namespace pv {
 namespace util {
 
-static const QString SIPrefixes[17] = {
-       "y", "z",
-       "a", "f", "p",
-       "n", QChar(0x03BC), "m",
-       "",
-       "k", "M", "G",
-       "T", "P", "E",
-       "Z", "Y"};
-const int EmptySIPrefix = 8;
-const int FirstSIPrefixPower = -(EmptySIPrefix * 3);
+static QTextStream& operator<<(QTextStream& stream, SIPrefix prefix)
+{
+       switch (prefix) {
+       case SIPrefix::yocto: return stream << 'y';
+       case SIPrefix::zepto: return stream << 'z';
+       case SIPrefix::atto:  return stream << 'a';
+       case SIPrefix::femto: return stream << 'f';
+       case SIPrefix::pico:  return stream << 'p';
+       case SIPrefix::nano:  return stream << 'n';
+       case SIPrefix::micro: return stream << QChar(0x03BC);
+       case SIPrefix::milli: return stream << 'm';
+       case SIPrefix::kilo:  return stream << 'k';
+       case SIPrefix::mega:  return stream << 'M';
+       case SIPrefix::giga:  return stream << 'G';
+       case SIPrefix::tera:  return stream << 'T';
+       case SIPrefix::peta:  return stream << 'P';
+       case SIPrefix::exa:   return stream << 'E';
+       case SIPrefix::zetta: return stream << 'Z';
+       case SIPrefix::yotta: return stream << 'Y';
+
+       default: return stream;
+       }
+}
+
+int exponent(SIPrefix prefix)
+{
+       return 3 * (static_cast<int>(prefix) - static_cast<int>(SIPrefix::none));
+}
+
+static SIPrefix successor(SIPrefix prefix)
+{
+       assert(prefix != SIPrefix::yotta);
+       return static_cast<SIPrefix>(static_cast<int>(prefix) + 1);
+}
 
 // Insert the timestamp value into the stream in fixed-point notation
 // (and honor the precision)
@@ -86,31 +110,29 @@ static QTextStream& operator<<(QTextStream& stream, const Timestamp& t)
        return stream << QString::fromStdString(str);
 }
 
-QString format_si_value(const Timestamp& v, QString unit, int prefix,
+QString format_si_value(const Timestamp& v, QString unit, SIPrefix prefix,
        unsigned int precision, bool sign)
 {
-       if (prefix < 0) {
+       if (prefix == SIPrefix::unspecified) {
                // No prefix given, calculate it
 
                if (v.is_zero()) {
-                       prefix = EmptySIPrefix;
+                       prefix = SIPrefix::none;
                } else {
-                       int exp = -FirstSIPrefixPower;
-
-                       prefix = 0;
-                       while ((fabs(v) * pow(10.0, exp)) > 999.0 &&
-                               prefix < (int)(countof(SIPrefixes) - 1)) {
-                               prefix++;
+                       int exp = exponent(SIPrefix::yotta);
+                       prefix = SIPrefix::yocto;
+                       while ((fabs(v) * pow(Timestamp(10), exp)) > 999 &&
+                                       prefix < SIPrefix::yotta) {
+                               prefix = successor(prefix);
                                exp -= 3;
                        }
                }
        }
 
-       assert(prefix >= 0);
-       assert(prefix < (int)countof(SIPrefixes));
+       assert(prefix >= SIPrefix::yocto);
+       assert(prefix <= SIPrefix::yotta);
 
-       const Timestamp multiplier = pow(Timestamp(10),
-               (int)- prefix * 3 - FirstSIPrefixPower);
+       const Timestamp multiplier = pow(Timestamp(10), -exponent(prefix));
 
        QString s;
        QTextStream ts(&s);
@@ -120,7 +142,7 @@ QString format_si_value(const Timestamp& v, QString unit, int prefix,
                << qSetRealNumberPrecision(precision)
                << (v * multiplier)
                << ' '
-               << SIPrefixes[prefix]
+               << prefix
                << unit;
 
        return s;
@@ -202,21 +224,20 @@ static QString format_time_in_full(const Timestamp& t, signed precision)
 }
 
 static QString format_time_with_si(const Timestamp& t, QString unit,
-       int prefix, unsigned int precision)
+       SIPrefix prefix, unsigned int precision)
 {
        // The precision is always given without taking the prefix into account
        // so we need to deduct the number of decimals the prefix might imply
-       const int prefix_order =
-               -(prefix * 3 + pv::util::FirstSIPrefixPower);
+       const int prefix_order = -exponent(prefix);
 
        const unsigned int relative_prec =
-               (prefix >= EmptySIPrefix) ? precision :
+               (prefix >= SIPrefix::none) ? precision :
                std::max((int)(precision - prefix_order), 0);
 
        return format_si_value(t, unit, prefix, relative_prec);
 }
 
-QString format_time(const Timestamp& t, int prefix, TimeUnit unit,
+QString format_time(const Timestamp& t, SIPrefix prefix, TimeUnit unit,
        unsigned int precision)
 {
        // Make 0 appear as 0, not random +0 or -0
@@ -224,7 +245,7 @@ QString format_time(const Timestamp& t, int prefix, TimeUnit unit,
                return "0";
 
        // If we have to use samples then we have no alternative formats
-       if (unit == Samples)
+       if (unit == TimeUnit::Samples)
                return format_time_with_si(t, "sa", prefix, precision);
 
        // View in "normal" range -> medium precision, medium step size
@@ -239,7 +260,7 @@ QString format_time(const Timestamp& t, int prefix, TimeUnit unit,
 
 QString format_second(const Timestamp& second)
 {
-       return format_si_value(second, "s", -1, 0, false);
+       return format_si_value(second, "s", SIPrefix::unspecified, 0, false);
 }
 
 } // namespace util
index e9689ec0d6b4248646c91124292495b730be719a..f2740d409d9af018b3dc92e290e404ea8335aa0f 100644 (file)
 namespace pv {
 namespace util {
 
-enum TimeUnit {
+enum class TimeUnit {
        Time = 1,
        Samples = 2
 };
 
+enum class SIPrefix {
+       unspecified = -1,
+       yocto, zepto,
+       atto, femto, pico,
+       nano, micro, milli,
+       none,
+       kilo, mega, giga,
+       tera, peta, exa,
+       zetta, yotta
+};
+
+/// Returns the exponent that corresponds to a given prefix.
+int exponent(SIPrefix prefix);
+
 /// Timestamp type providing yoctosecond resolution.
 typedef boost::multiprecision::number<
        boost::multiprecision::cpp_dec_float<24>,
        boost::multiprecision::et_off> Timestamp;
 
-extern const int FirstSIPrefixPower;
-
 /**
  * Formats a given value with the specified SI prefix.
  * @param v The value to format.
  * @param unit The unit of quantity.
- * @param prefix The number of the prefix, from 0 for 'yotta' up to
- *   16 for 'yokto'. If prefix is set to -1, the prefix will be calculated.
+ * @param prefix The prefix to use.
  * @param precision The number of digits after the decimal separator.
  * @param sign Whether or not to add a sign also for positive numbers.
  *
  * @return The formated value.
  */
 QString format_si_value(
-       const Timestamp& v, QString unit, int prefix = -1,
+       const Timestamp& v, QString unit, SIPrefix prefix = SIPrefix::unspecified,
        unsigned precision = 0, bool sign = true);
 
 /**
  * Formats a given time with the specified SI prefix.
  * @param t The time value in seconds to format.
- * @param prefix The number of the prefix, from 0 for 'yotta' up to
- *   16 for 'yokto'. If prefix is set to -1, the prefix will be calculated.
+ * @param prefix The prefix to use.
  * @param unit The unit of quantity.
  * @param precision The number of digits after the decimal separator or period (.).
  *
  * @return The formated value.
  */
 QString format_time(
-       const Timestamp& t, int prefix = -1,
-       TimeUnit unit = Time, unsigned precision = 0);
+       const Timestamp& t, SIPrefix prefix = SIPrefix::unspecified,
+       TimeUnit unit = TimeUnit::Time, unsigned precision = 0);
 
 /**
  * Formats a given time value with a SI prefix so that the
index 7b9f671f036f603809ec420d172cde2198d7f479..7aa989da469061bf16ad621bfe701f40b7141254 100644 (file)
@@ -161,11 +161,11 @@ void CursorPair::paint_back(QPainter &p, const ViewItemPaintParams &pp) {
 
 QString CursorPair::format_string()
 {
-       const unsigned int prefix = view_.tick_prefix();
+       const pv::util::SIPrefix prefix = view_.tick_prefix();
        const pv::util::Timestamp delta = second_->time() - first_->time();
        return QString("%1 / %2").
                arg(util::format_time(delta, prefix, view_.time_unit(), 2)).
-               arg(util::format_si_value(1.0 / fabs(delta), "Hz", -1, 4));
+               arg(util::format_si_value(1 / fabs(delta), "Hz", pv::util::SIPrefix::unspecified, 4));
 }
 
 void CursorPair::compute_text_size(QPainter &p)
index 652c4f8087e637c32e1a94068b8dabdb6fbd6ab3..dbae983389691a013ca86f36619ff5f5bfe8723a 100644 (file)
@@ -104,9 +104,9 @@ View::View(Session &session, QWidget *parent) :
        sticky_scrolling_(false), // Default setting is set in MainWindow::setup_ui()
        always_zoom_to_fit_(false),
        tick_period_(0.0),
-       tick_prefix_(0),
+       tick_prefix_(pv::util::SIPrefix::yocto),
        tick_precision_(0),
-       time_unit_(util::Time),
+       time_unit_(util::TimeUnit::Time),
        show_cursors_(false),
        cursors_(new CursorPair(*this)),
        next_flag_text_('A'),
@@ -233,7 +233,7 @@ unsigned int View::depth() const
        return 0;
 }
 
-unsigned int View::tick_prefix() const
+pv::util::SIPrefix View::tick_prefix() const
 {
        return tick_prefix_;
 }
@@ -529,7 +529,8 @@ void View::calculate_tick_spacing()
                } while (tp_with_margin < min_period && unit < countof(ScaleUnits));
 
                tick_period_ = order_decimal * ScaleUnits[unit - 1];
-               tick_prefix_ = (order - pv::util::FirstSIPrefixPower) / 3;
+               tick_prefix_ = static_cast<pv::util::SIPrefix>(
+                       (order - pv::util::exponent(pv::util::SIPrefix::yocto)) / 3);
 
                // Precision is the number of fractional digits required, not
                // taking the prefix into account (and it must never be negative)
@@ -679,7 +680,7 @@ vector< shared_ptr<Trace> > View::extract_new_traces_for_channels(
 void View::determine_time_unit()
 {
        // Check whether we know the sample rate and hence can use time as the unit
-       if (time_unit_ == util::Samples) {
+       if (time_unit_ == util::TimeUnit::Samples) {
                shared_lock<shared_mutex> lock(session().signals_mutex());
                const unordered_set< shared_ptr<Signal> > &sigs(session().signals());
 
@@ -691,7 +692,7 @@ void View::determine_time_unit()
                        const vector< shared_ptr<Segment> > segments = data->segments();
                        if (!segments.empty())
                                if (segments[0]->samplerate()) {
-                                       time_unit_ = util::Time;
+                                       time_unit_ = util::TimeUnit::Time;
                                        break;
                                }
                }
@@ -932,7 +933,7 @@ void View::signals_changed()
 void View::capture_state_updated(int state)
 {
        if (state == Session::Running)
-               time_unit_ = util::Samples;
+               time_unit_ = util::TimeUnit::Samples;
 
        if (state == Session::Stopped) {
                // After acquisition has stopped we need to re-calculate the ticks once
index 12527b656d80943f2abb8d69039d33729d45adc0..ed1c92633da5348384e6f4081f185448986656df 100644 (file)
@@ -123,7 +123,7 @@ public:
        /**
         * Returns the SI prefix to apply to the graticule time markings.
         */
-       unsigned int tick_prefix() const;
+       pv::util::SIPrefix tick_prefix() const;
 
        /**
         * Returns the number of fractional digits shown for the time markings.
@@ -319,7 +319,7 @@ private:
        QTimer delayed_view_updater_;
 
        double tick_period_;
-       unsigned int tick_prefix_;
+       pv::util::SIPrefix tick_prefix_;
        unsigned int tick_precision_;
        util::TimeUnit time_unit_;
 
index 703da6ea13cb51aaf2f9581c4cbbbbea7cc19def..59af82f65407629b0937ec66bc14308b190188d1 100644 (file)
@@ -114,7 +114,7 @@ void TimestampSpinBox::on_editingFinished()
 void TimestampSpinBox::updateEdit()
 {
        QString newtext = pv::util::format_si_value(
-               value_, "s", 8, precision_);
+               value_, "s", pv::util::SIPrefix::none, precision_);
        lineEdit()->setText(newtext);
 }
 
index ce9b64d27f324cf3f6cc561fe76b2db3c90dc1cc..70550ae660c34115b6bc334ef0a01fdc4b20a36d 100644 (file)
@@ -27,6 +27,16 @@ using ts = pv::util::Timestamp;
 
 namespace {
        QChar mu = QChar(0x03BC);
+
+       pv::util::SIPrefix unspecified = pv::util::SIPrefix::unspecified;
+       pv::util::SIPrefix yocto       = pv::util::SIPrefix::yocto;
+       pv::util::SIPrefix micro       = pv::util::SIPrefix::micro;
+       pv::util::SIPrefix milli       = pv::util::SIPrefix::milli;
+       pv::util::SIPrefix none        = pv::util::SIPrefix::none;
+       pv::util::SIPrefix kilo        = pv::util::SIPrefix::kilo;
+       pv::util::SIPrefix yotta       = pv::util::SIPrefix::yotta;
+
+       pv::util::TimeUnit Time = pv::util::TimeUnit::Time;
 }
 
 std::ostream& operator<<(std::ostream& stream, const QString& str)
@@ -36,6 +46,27 @@ std::ostream& operator<<(std::ostream& stream, const QString& str)
 
 BOOST_AUTO_TEST_SUITE(UtilTest)
 
+BOOST_AUTO_TEST_CASE(exponent_test)
+{
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::yocto), -24);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::zepto), -21);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::atto),  -18);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::femto), -15);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::pico),  -12);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::nano),   -9);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::micro),  -6);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::milli),  -3);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::none),    0);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::kilo),    3);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::mega),    6);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::giga),    9);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::tera),   12);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::peta),   15);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::exa),    18);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::zetta),  21);
+       BOOST_CHECK_EQUAL(exponent(SIPrefix::yotta),  24);
+}
+
 BOOST_AUTO_TEST_CASE(format_si_value_test)
 {
        // check prefix calculation
@@ -96,30 +127,30 @@ BOOST_AUTO_TEST_CASE(format_si_value_test)
        BOOST_CHECK_EQUAL(format_si_value(ts("1e27"), "V"), "+1000 YV");
 
        BOOST_CHECK_EQUAL(format_si_value(ts("1234"), "V"),           "+1 kV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1234"), "V", 9, 3), "+1.234 kV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1234"), "V", kilo, 3), "+1.234 kV");
        BOOST_CHECK_EQUAL(format_si_value(ts("1234.5678"), "V"),      "+1 kV");
 
        // check if a given prefix is honored
 
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-24"), "V", 0),    "+1 yV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-21"), "V", 0), "+1000 yV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", 0),         "0 yV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-24"), "V", yocto),    "+1 yV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-21"), "V", yocto), "+1000 yV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", yocto),         "0 yV");
 
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-4"), "V", 7),       "+0 mV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-4"), "V", 7, 1),  "+0.1 mV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1000"), "V", 7), "+1000000 mV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", 7),           "0 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-4"), "V", milli),       "+0 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-4"), "V", milli, 1),  "+0.1 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1000"), "V", milli), "+1000000 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", milli),           "0 mV");
 
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", 8),       "+0 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", 8, 1),  "+0.1 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", 8, 2), "+0.10 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", 8),          "+1 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e1"), "V", 8),       "+10 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", none),       "+0 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", none, 1),  "+0.1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e-1"), "V", none, 2), "+0.10 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", none),          "+1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e1"), "V", none),       "+10 V");
 
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e23"), "V", 16),       "+0 YV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e23"), "V", 16, 1),  "+0.1 YV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1e27"), "V", 16),    "+1000 YV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", 16),           "0 YV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e23"), "V", yotta),       "+0 YV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e23"), "V", yotta, 1),  "+0.1 YV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1e27"), "V", yotta),    "+1000 YV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("0"), "V", yotta),           "0 YV");
 
        // check precision
 
@@ -127,66 +158,66 @@ BOOST_AUTO_TEST_CASE(format_si_value_test)
        BOOST_CHECK_EQUAL(format_si_value(ts("1.4"), "V"),                      "+1 V");
        BOOST_CHECK_EQUAL(format_si_value(ts("1.5"), "V"),                      "+2 V");
        BOOST_CHECK_EQUAL(format_si_value(ts("1.9"), "V"),                      "+2 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", -1, 2),      "+1.23 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", -1, 3),     "+1.235 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", 7, 3),  "+1234.568 mV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", 7, 0),      "+1235 mV");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1.2"), "V", -1, 3),           "+1.200 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", unspecified, 2),      "+1.23 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", unspecified, 3),     "+1.235 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", milli, 3),       "+1234.568 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1.2345678"), "V", milli, 0),           "+1235 mV");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1.2"), "V", unspecified, 3),           "+1.200 V");
 
        // check sign
 
-       BOOST_CHECK_EQUAL(format_si_value(ts("-1"), "V", 8, 0, true),  "-1 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("-1"), "V", 8, 0, false), "-1 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", 8, 0, true),   "+1 V");
-       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", 8, 0, false),   "1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("-1"), "V", none, 0, true),  "-1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("-1"), "V", none, 0, false), "-1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", none, 0, true),   "+1 V");
+       BOOST_CHECK_EQUAL(format_si_value(ts("1"), "V", none, 0, false),   "1 V");
 }
 
 BOOST_AUTO_TEST_CASE(format_time_test)
 {
-       BOOST_CHECK_EQUAL(format_time(ts("-0.00005"), 6, Time, 5), QString("-50 ") + mu + "s");
-       BOOST_CHECK_EQUAL(format_time(ts( "0.00005"), 6, Time, 5), QString("+50 ") + mu + "s");
+       BOOST_CHECK_EQUAL(format_time(ts("-0.00005"), micro, Time, 5), QString("-50 ") + mu + "s");
+       BOOST_CHECK_EQUAL(format_time(ts( "0.00005"), micro, Time, 5), QString("+50 ") + mu + "s");
        BOOST_CHECK_EQUAL(format_time(ts( "1")), "+1 s");
        BOOST_CHECK_EQUAL(format_time(ts("-1")), "-1 s");
-       BOOST_CHECK_EQUAL(format_time(ts( "100")),                 "+1:40");
-       BOOST_CHECK_EQUAL(format_time(ts("-100")),                 "-1:40");
-       BOOST_CHECK_EQUAL(format_time(ts( "4000")),             "+1:06:40");
-       BOOST_CHECK_EQUAL(format_time(ts("-4000")),             "-1:06:40");
-       BOOST_CHECK_EQUAL(format_time(ts("12000"), 9, Time, 0), "+3:20:00");
-       BOOST_CHECK_EQUAL(format_time(ts("15000"), 9, Time, 0), "+4:10:00");
-       BOOST_CHECK_EQUAL(format_time(ts("20000"), 9, Time, 0), "+5:33:20");
-       BOOST_CHECK_EQUAL(format_time(ts("25000"), 9, Time, 0), "+6:56:40");
-
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 0), "+123:04:05:06");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 1), "+123:04:05:06.0");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 2), "+123:04:05:06.00");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 3), "+123:04:05:06.007");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 4), "+123:04:05:06.007 0");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 5), "+123:04:05:06.007 00");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 6), "+123:04:05:06.007 008");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 7), "+123:04:05:06.007 008 0");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 8), "+123:04:05:06.007 008 00");
-       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), 0, Time, 9), "+123:04:05:06.007 008 009");
-
-       BOOST_CHECK_EQUAL(format_time(ts("-1.5"), 7), "-1500 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("-1.0"), 7), "-1000 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("-0.2")),     "-200 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("-0.1")),     "-100 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.0")),         "0");
-       BOOST_CHECK_EQUAL(format_time(ts("0.1")),      "+100 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.2")),      "+200 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.3")),      "+300 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.4")),      "+400 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.5")),      "+500 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.6")),      "+600 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.7")),      "+700 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.8")),      "+800 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("0.9")),      "+900 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.0"), 7),  "+1000 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.1"), 7),  "+1100 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.2"), 7),  "+1200 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.3"), 7),  "+1300 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.4"), 7),  "+1400 ms");
-       BOOST_CHECK_EQUAL(format_time(ts("1.5"), 7),  "+1500 ms");
+       BOOST_CHECK_EQUAL(format_time(ts( "100")),                    "+1:40");
+       BOOST_CHECK_EQUAL(format_time(ts("-100")),                    "-1:40");
+       BOOST_CHECK_EQUAL(format_time(ts( "4000")),                "+1:06:40");
+       BOOST_CHECK_EQUAL(format_time(ts("-4000")),                "-1:06:40");
+       BOOST_CHECK_EQUAL(format_time(ts("12000"), kilo, Time, 0), "+3:20:00");
+       BOOST_CHECK_EQUAL(format_time(ts("15000"), kilo, Time, 0), "+4:10:00");
+       BOOST_CHECK_EQUAL(format_time(ts("20000"), kilo, Time, 0), "+5:33:20");
+       BOOST_CHECK_EQUAL(format_time(ts("25000"), kilo, Time, 0), "+6:56:40");
+
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 0), "+123:04:05:06");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 1), "+123:04:05:06.0");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 2), "+123:04:05:06.00");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 3), "+123:04:05:06.007");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 4), "+123:04:05:06.007 0");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 5), "+123:04:05:06.007 00");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 6), "+123:04:05:06.007 008");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 7), "+123:04:05:06.007 008 0");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 8), "+123:04:05:06.007 008 00");
+       BOOST_CHECK_EQUAL(format_time(ts("10641906.007008009"), none, Time, 9), "+123:04:05:06.007 008 009");
+
+       BOOST_CHECK_EQUAL(format_time(ts("-1.5"), milli), "-1500 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("-1.0"), milli), "-1000 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("-0.2")),         "-200 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("-0.1")),         "-100 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.0")),             "0");
+       BOOST_CHECK_EQUAL(format_time(ts("0.1")),          "+100 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.2")),          "+200 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.3")),          "+300 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.4")),          "+400 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.5")),          "+500 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.6")),          "+600 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.7")),          "+700 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.8")),          "+800 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("0.9")),          "+900 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.0"), milli),  "+1000 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.1"), milli),  "+1100 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.2"), milli),  "+1200 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.3"), milli),  "+1300 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.4"), milli),  "+1400 ms");
+       BOOST_CHECK_EQUAL(format_time(ts("1.5"), milli),  "+1500 ms");
 }
 
 BOOST_AUTO_TEST_SUITE_END()