From 4657b4de1cd8075ebb88ab42932a7a5fc37f43c4 Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Tue, 31 Jul 2018 18:20:32 +0200
Subject: [PATCH] PhysUnits included

---
 third_party/phys/units/io.hpp                 |  27 +
 third_party/phys/units/io_output.hpp          |  25 +
 third_party/phys/units/io_output_eng.hpp      |  26 +
 third_party/phys/units/io_symbols.hpp         |  25 +
 third_party/phys/units/other_units.hpp        | 218 ++++
 third_party/phys/units/physical_constants.hpp |  61 ++
 third_party/phys/units/quantity.hpp           | 967 ++++++++++++++++++
 third_party/phys/units/quantity_io.hpp        | 251 +++++
 third_party/phys/units/quantity_io_ampere.hpp |  39 +
 .../phys/units/quantity_io_becquerel.hpp      |  45 +
 .../phys/units/quantity_io_candela.hpp        |  39 +
 .../phys/units/quantity_io_celsius.hpp        |  46 +
 .../phys/units/quantity_io_coulomb.hpp        |  45 +
 .../phys/units/quantity_io_dimensionless.hpp  |  40 +
 .../phys/units/quantity_io_engineering.hpp    | 173 ++++
 third_party/phys/units/quantity_io_farad.hpp  |  45 +
 third_party/phys/units/quantity_io_gray.hpp   |  45 +
 third_party/phys/units/quantity_io_henry.hpp  |  45 +
 third_party/phys/units/quantity_io_hertz.hpp  |  45 +
 third_party/phys/units/quantity_io_joule.hpp  |  45 +
 third_party/phys/units/quantity_io_kelvin.hpp |  39 +
 .../phys/units/quantity_io_kilogram.hpp       |  39 +
 third_party/phys/units/quantity_io_lumen.hpp  |  45 +
 third_party/phys/units/quantity_io_lux.hpp    |  45 +
 third_party/phys/units/quantity_io_meter.hpp  |  39 +
 third_party/phys/units/quantity_io_mole.hpp   |  39 +
 third_party/phys/units/quantity_io_newton.hpp |  45 +
 third_party/phys/units/quantity_io_ohm.hpp    |  45 +
 third_party/phys/units/quantity_io_pascal.hpp |  45 +
 third_party/phys/units/quantity_io_radian.hpp |  44 +
 third_party/phys/units/quantity_io_second.hpp |  39 +
 .../phys/units/quantity_io_siemens.hpp        |  45 +
 .../phys/units/quantity_io_sievert.hpp        |  45 +
 third_party/phys/units/quantity_io_speed.hpp  |  45 +
 .../phys/units/quantity_io_steradian.hpp      |  44 +
 .../phys/units/quantity_io_symbols.hpp        |  57 ++
 third_party/phys/units/quantity_io_tesla.hpp  |  45 +
 third_party/phys/units/quantity_io_volt.hpp   |  45 +
 third_party/phys/units/quantity_io_watt.hpp   |  45 +
 third_party/phys/units/quantity_io_weber.hpp  |  45 +
 40 files changed, 3132 insertions(+)
 create mode 100644 third_party/phys/units/io.hpp
 create mode 100644 third_party/phys/units/io_output.hpp
 create mode 100644 third_party/phys/units/io_output_eng.hpp
 create mode 100644 third_party/phys/units/io_symbols.hpp
 create mode 100644 third_party/phys/units/other_units.hpp
 create mode 100644 third_party/phys/units/physical_constants.hpp
 create mode 100644 third_party/phys/units/quantity.hpp
 create mode 100644 third_party/phys/units/quantity_io.hpp
 create mode 100644 third_party/phys/units/quantity_io_ampere.hpp
 create mode 100644 third_party/phys/units/quantity_io_becquerel.hpp
 create mode 100644 third_party/phys/units/quantity_io_candela.hpp
 create mode 100644 third_party/phys/units/quantity_io_celsius.hpp
 create mode 100644 third_party/phys/units/quantity_io_coulomb.hpp
 create mode 100644 third_party/phys/units/quantity_io_dimensionless.hpp
 create mode 100644 third_party/phys/units/quantity_io_engineering.hpp
 create mode 100644 third_party/phys/units/quantity_io_farad.hpp
 create mode 100644 third_party/phys/units/quantity_io_gray.hpp
 create mode 100644 third_party/phys/units/quantity_io_henry.hpp
 create mode 100644 third_party/phys/units/quantity_io_hertz.hpp
 create mode 100644 third_party/phys/units/quantity_io_joule.hpp
 create mode 100644 third_party/phys/units/quantity_io_kelvin.hpp
 create mode 100644 third_party/phys/units/quantity_io_kilogram.hpp
 create mode 100644 third_party/phys/units/quantity_io_lumen.hpp
 create mode 100644 third_party/phys/units/quantity_io_lux.hpp
 create mode 100644 third_party/phys/units/quantity_io_meter.hpp
 create mode 100644 third_party/phys/units/quantity_io_mole.hpp
 create mode 100644 third_party/phys/units/quantity_io_newton.hpp
 create mode 100644 third_party/phys/units/quantity_io_ohm.hpp
 create mode 100644 third_party/phys/units/quantity_io_pascal.hpp
 create mode 100644 third_party/phys/units/quantity_io_radian.hpp
 create mode 100644 third_party/phys/units/quantity_io_second.hpp
 create mode 100644 third_party/phys/units/quantity_io_siemens.hpp
 create mode 100644 third_party/phys/units/quantity_io_sievert.hpp
 create mode 100644 third_party/phys/units/quantity_io_speed.hpp
 create mode 100644 third_party/phys/units/quantity_io_steradian.hpp
 create mode 100644 third_party/phys/units/quantity_io_symbols.hpp
 create mode 100644 third_party/phys/units/quantity_io_tesla.hpp
 create mode 100644 third_party/phys/units/quantity_io_volt.hpp
 create mode 100644 third_party/phys/units/quantity_io_watt.hpp
 create mode 100644 third_party/phys/units/quantity_io_weber.hpp

diff --git a/third_party/phys/units/io.hpp b/third_party/phys/units/io.hpp
new file mode 100644
index 00000000..9bb53384
--- /dev/null
+++ b/third_party/phys/units/io.hpp
@@ -0,0 +1,27 @@
+/**
+ * \file io.hpp
+ *
+ * \brief   IO for compile-time quantity library.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_IO_HPP_INCLUDED
+#define PHYS_UNITS_IO_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+#include "phys/units/quantity_io_engineering.hpp"
+#include "phys/units/quantity_io_symbols.hpp"
+
+#endif // PHYS_UNITS_IO_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/io_output.hpp b/third_party/phys/units/io_output.hpp
new file mode 100644
index 00000000..f9095a92
--- /dev/null
+++ b/third_party/phys/units/io_output.hpp
@@ -0,0 +1,25 @@
+/**
+ * \file io_output.hpp
+ *
+ * \brief   IO for quantity library.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_IO_OUTPUT_HPP_INCLUDED
+#define PHYS_UNITS_IO_OUTPUT_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+#endif // PHYS_UNITS_IO_OUTPUT_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/io_output_eng.hpp b/third_party/phys/units/io_output_eng.hpp
new file mode 100644
index 00000000..47bc2e2e
--- /dev/null
+++ b/third_party/phys/units/io_output_eng.hpp
@@ -0,0 +1,26 @@
+/**
+ * \file io_output_eng.hpp
+ *
+ * \brief   Engineering IO for quantity library.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_IO_ENG_HPP_INCLUDED
+#define PHYS_UNITS_IO_ENG_HPP_INCLUDED
+
+#include "phys/units/quantity_io_engineering.hpp"
+
+#endif // PHYS_UNITS_IO_ENG_HPP_INCLUDED
+
+/*
+ * end of file
+ */
+
diff --git a/third_party/phys/units/io_symbols.hpp b/third_party/phys/units/io_symbols.hpp
new file mode 100644
index 00000000..b91666ee
--- /dev/null
+++ b/third_party/phys/units/io_symbols.hpp
@@ -0,0 +1,25 @@
+/**
+ * \file io_symbols.hpp
+ *
+ * \brief   IO for quantity library.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_IO_SYMBOLS_HPP_INCLUDED
+#define PHYS_UNITS_IO_SYMBOLS_HPP_INCLUDED
+
+#include "phys/units/quantity_io_symbols.hpp"
+
+#endif // PHYS_UNITS_IO_SYMBOLS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/other_units.hpp b/third_party/phys/units/other_units.hpp
new file mode 100644
index 00000000..3e6c3554
--- /dev/null
+++ b/third_party/phys/units/other_units.hpp
@@ -0,0 +1,218 @@
+/**
+ * \file other_units.hpp
+ *
+ * \brief   Units not approved for use with SI.
+ * \author  Michael S. Kenniston
+ * \date    16 July 2001
+ * \since   0.4
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ *
+ * Copyright (c) 2001 by Michael S. Kenniston.  For the most
+ * recent version check www.xnet.com/~msk/quantity.  Permission is granted
+ * to use this code without restriction so long as this copyright
+ * notice appears in all source files.
+ *
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * This file contains the definitions of units that are *NOT* approved
+ * for use with SI, as specified by SP811.  These units should not
+ * be used with any new work.  However, they may be needed for
+ * handling and converting legacy data.
+ */
+
+#ifndef PHYS_UNITS_OTHER_UNITS_HPP_INCLUDED
+#define PHYS_UNITS_OTHER_UNITS_HPP_INCLUDED
+
+#include "phys/units/quantity.hpp"
+
+namespace phys { namespace units {
+
+constexpr quantity< electric_current_d >     abampere           { Rep( 1e+1L ) * ampere };
+constexpr quantity< electric_charge_d >      abcoulomb          { Rep( 1e+1L ) * coulomb };
+constexpr quantity< capacitance_d >          abfarad            { Rep( 1e+9L ) * farad };
+constexpr quantity< inductance_d >           abhenry            { Rep( 1e-9L ) * henry };
+constexpr quantity< electric_conductance_d > abmho              { Rep( 1e+9L ) * siemens };
+constexpr quantity< electric_resistance_d >  abohm              { Rep( 1e-9L ) * ohm };
+constexpr quantity< electric_potential_d >   abvolt             { Rep( 1e-8L ) * volt };
+constexpr quantity< area_d >                 acre               { Rep( 4.046873e+3L ) * square( meter ) };
+constexpr quantity< volume_d >               acre_foot          { Rep( 1.233489e+3L ) * cube( meter ) };
+constexpr quantity< length_d >               astronomical_unit  { Rep( 1.495979e+11L ) * meter };
+constexpr quantity< pressure_d >             atmosphere_std     { Rep( 1.01325e+5L ) * pascal };
+constexpr quantity< pressure_d >             atmosphere_tech    { Rep( 9.80665e+4L ) * pascal };
+
+constexpr quantity< volume_d >               barrel             { Rep( 1.589873e-1L ) * cube( meter ) };
+constexpr quantity< electric_current_d >     biot               { Rep( 1e+1L ) * ampere };
+constexpr quantity< energy_d >               btu                { Rep( 1.05587e+3L ) * joule };
+constexpr quantity< energy_d >               btu_it             { Rep( 1.055056e+3L ) * joule };
+constexpr quantity< energy_d >               btu_th             { Rep( 1.054350e+3L ) * joule };
+constexpr quantity< energy_d >               btu_39F            { Rep( 1.05967e+3L ) * joule };
+constexpr quantity< energy_d >               btu_59F            { Rep( 1.05480e+3L ) * joule };
+constexpr quantity< energy_d >               btu_60F            { Rep( 1.05468e+3L ) * joule };
+constexpr quantity< volume_d >               bushel             { Rep( 3.523907e-2L ) * cube( meter ) };
+
+constexpr quantity< energy_d >               calorie            { Rep( 4.19002L ) * joule };
+constexpr quantity< energy_d >               calorie_it         { Rep( 4.1868L ) * joule };
+constexpr quantity< energy_d >               calorie_th         { Rep( 4.184L ) * joule };
+constexpr quantity< energy_d >               calorie_15C        { Rep( 4.18580L ) * joule };
+constexpr quantity< energy_d >               calorie_20C        { Rep( 4.18190L ) * joule };
+constexpr quantity< mass_d >                 carat_metric       { Rep( 2e-4L ) * kilogram };
+constexpr quantity< length_d >               chain              { Rep( 2.011684e+1L ) * meter };
+constexpr quantity< thermal_insulance_d >    clo                { Rep( 1.55e-1L ) * square( meter ) * kelvin / watt };
+constexpr quantity< pressure_d >             cm_mercury         { Rep( 1.333224e+3L ) * pascal };
+constexpr quantity< volume_d >               cord               { Rep( 3.624556L ) * cube( meter ) };
+constexpr quantity< volume_d >               cup                { Rep( 2.365882e-4L ) * cube( meter ) };
+
+constexpr quantity< dimensions< 2, 0, 0 >>   darcy              { Rep( 9.869233e-13L ) * square( meter ) };
+constexpr quantity< time_interval_d >        day_sidereal       { Rep( 8.616409e+4L ) * second };
+constexpr quantity< dimensions< 1, 0, 1, 1>> debye              { Rep( 3.335641e-30L ) * coulomb * meter };
+constexpr quantity< thermodynamic_temperature_d > degree_fahrenheit{ Rep( 5.555556e-1L ) * kelvin };
+constexpr quantity< thermodynamic_temperature_d > degree_rankine   { Rep( 5.555556e-1L ) * kelvin };
+constexpr quantity< dimensions< -1, 1, 0 >>  denier             { Rep( 1.111111e-7L ) * kilogram / meter };
+constexpr quantity< force_d >                dyne               { Rep( 1e-5L ) * newton };
+
+constexpr quantity< energy_d >               erg                { Rep( 1e-7L ) * joule };
+
+constexpr quantity< electric_charge_d >      faraday            { Rep( 9.648531e+4L ) * coulomb };
+constexpr quantity< length_d >               fathom             { Rep( 1.828804L ) * meter };
+constexpr quantity< length_d >               fermi              { Rep( 1e-15L ) * meter };
+constexpr quantity< length_d >               foot               { Rep( 3.048e-1L ) * meter };
+constexpr quantity< energy_d >               foot_pound_force   { Rep( 1.355818L ) * joule };
+constexpr quantity< energy_d >               foot_poundal       { Rep( 4.214011e-2L ) * joule };
+constexpr quantity< length_d >               foot_us_survey     { Rep( 3.048006e-1L ) * meter };
+constexpr quantity< illuminance_d >          footcandle         { Rep( 1.076391e+1L ) * lux };
+constexpr quantity< illuminance_d >          footlambert        { Rep( 3.426259L ) * candela / square( meter ) };
+constexpr quantity< time_interval_d >        fortnight          { Rep( 14 ) * day }; // from OED
+constexpr quantity< electric_charge_d >      franklin           { Rep( 3.335641e-10L ) * coulomb };
+constexpr quantity< length_d >               furlong            { Rep( 2.01168e+2L ) * meter }; // from OED
+
+constexpr quantity< volume_d >               gallon_imperial    { Rep( 4.54609e-3L ) * cube( meter ) };
+constexpr quantity< volume_d >               gallon_us          { Rep( 3.785412e-3L ) * cube( meter ) };
+constexpr quantity< magnetic_flux_density_d > gamma             { Rep( 1e-9L ) * tesla };
+constexpr quantity< mass_d >                 gamma_mass         { Rep( 1e-9L ) * kilogram };
+constexpr quantity< magnetic_flux_density_d > gauss             { Rep( 1e-4L ) * tesla };
+constexpr quantity< electric_current_d >     gilbert            { Rep( 7.957747e-1L ) * ampere };
+constexpr quantity< volume_d >               gill_imperial      { Rep( 1.420653e-4L ) * cube( meter ) };
+constexpr quantity< volume_d >               gill_us            { Rep( 1.182941e-4L ) * cube( meter ) };
+constexpr Rep                                gon                { Rep( 9e-1L ) * degree_angle };
+constexpr quantity< mass_d >                 grain              { Rep( 6.479891e-5L ) * kilogram };
+
+constexpr quantity< power_d >                horsepower         { Rep( 7.456999e+2L ) * watt };
+constexpr quantity< power_d >                horsepower_boiler  { Rep( 9.80950e+3L ) * watt };
+constexpr quantity< power_d >                horsepower_electric{ Rep( 7.46e+2L ) * watt };
+constexpr quantity< power_d >                horsepower_metric  { Rep( 7.354988e+2L ) * watt };
+constexpr quantity< power_d >                horsepower_uk      { Rep( 7.4570e+2L ) * watt };
+constexpr quantity< power_d >                horsepower_water   { Rep( 7.46043e+2L ) * watt };
+constexpr quantity< time_interval_d >        hour_sidereal      { Rep( 3.590170e+3L ) * second };
+constexpr quantity< mass_d >                 hundredweight_long { Rep( 5.080235e+1L ) * kilogram };
+constexpr quantity< mass_d >                 hundredweight_short{ Rep( 4.535924e+1L ) * kilogram };
+
+constexpr quantity< length_d >               inch               { Rep( 2.54e-2L ) * meter };
+constexpr quantity< pressure_d >             inches_mercury     { Rep( 3.386389e+3L ) * pascal };
+
+constexpr quantity< wave_number_d >          kayser             { Rep( 1e+2 ) / meter };
+constexpr quantity< force_d >                kilogram_force     { Rep( 9.80665 ) * newton };
+constexpr quantity< force_d >                kilopond           { Rep( 9.80665 ) * newton };
+constexpr quantity< force_d >                kip                { Rep( 4.448222e+3L ) * newton };
+
+constexpr quantity< volume_d >               lambda_volume      { Rep( 1e-9L ) * cube( meter ) };
+constexpr quantity< illuminance_d >          lambert            { Rep( 3.183099e+3L ) * candela / square( meter ) };
+constexpr quantity< heat_density_d >         langley            { Rep( 4.184e+4L ) * joule / square( meter ) };
+constexpr quantity< length_d >               light_year         { Rep( 9.46073e+15L ) * meter };
+
+constexpr quantity< magnetic_flux_d >        maxwell            { Rep( 1e-8L ) * weber };
+constexpr quantity< electric_conductance_d > mho                { siemens };
+constexpr quantity< length_d >               micron             { micro * meter };
+constexpr quantity< length_d >               mil                { Rep( 2.54e-5L ) * meter };
+constexpr Rep                                mil_angle          { Rep( 5.625e-2L ) * degree_angle };
+constexpr quantity< area_d >                 mil_circular       { Rep( 5.067075e-10L ) * square( meter ) };
+constexpr quantity< length_d >               mile               { Rep( 1.609344e+3L ) * meter };
+constexpr quantity< length_d >               mile_us_survey     { Rep( 1.609347e+3L ) * meter };
+constexpr quantity< time_interval_d >        minute_sidereal    { Rep( 5.983617e+1L ) * second };
+
+constexpr quantity< dimensions< -1, 0, 0, 1 > >oersted          { Rep( 7.957747e+1L ) * ampere / meter };
+constexpr quantity< mass_d >                 ounce_avdp         { Rep( 2.834952e-2L ) * kilogram };
+constexpr quantity< volume_d >               ounce_fluid_imperial{ Rep( 2.841306e-5L ) * cube( meter ) };
+constexpr quantity< volume_d >               ounce_fluid_us     { Rep( 2.957353e-5L ) * cube( meter ) };
+constexpr quantity< force_d >                ounce_force        { Rep( 2.780139e-1L ) * newton };
+constexpr quantity< mass_d >                 ounce_troy         { Rep( 3.110348e-2L ) * kilogram };
+
+constexpr quantity< length_d >               parsec             { Rep( 3.085678e+16L ) * meter };
+constexpr quantity< volume_d >               peck               { Rep( 8.809768e-3L ) * cube( meter ) };
+constexpr quantity< mass_d >                 pennyweight        { Rep( 1.555174e-3L ) * kilogram };
+constexpr quantity< substance_permeability_d >  perm_0C         { Rep( 5.72135e-11L ) * kilogram / pascal / second / square( meter ) };
+constexpr quantity< substance_permeability_d >  perm_23C        { Rep( 5.74525e-11L ) * kilogram / pascal / second / square( meter ) };
+constexpr quantity< illuminance_d >          phot               { Rep( 1e+4L ) * lux };
+constexpr quantity< length_d >               pica_computer      { Rep( 4.233333e-3L ) * meter };
+constexpr quantity< length_d >               pica_printers      { Rep( 4.217518e-3L ) * meter };
+constexpr quantity< volume_d >               pint_dry           { Rep( 5.506105e-4L ) * cube( meter ) };
+constexpr quantity< volume_d >               pint_liquid        { Rep( 4.731765e-4L ) * cube( meter ) };
+constexpr quantity< length_d >               point_computer     { Rep( 3.527778e-4L ) * meter };
+constexpr quantity< length_d >               point_printers     { Rep( 3.514598e-4L ) * meter };
+constexpr quantity< dynamic_viscosity_d >    poise              { Rep( 1e-1L ) * pascal * second };
+constexpr quantity< mass_d >                 pound_avdp         { Rep( 4.5359237e-1L ) * kilogram };
+constexpr quantity< force_d >                pound_force        { Rep( 4.448222L ) * newton };
+constexpr quantity< mass_d >                 pound_troy         { Rep( 3.732417e-1L ) * kilogram };
+constexpr quantity< force_d >                poundal            { Rep( 1.382550e-1L ) * newton };
+constexpr quantity< pressure_d >             psi                { Rep( 6.894757e+3L ) * pascal };
+
+constexpr quantity< energy_d >               quad               { Rep( 1e+15L ) * btu_it };
+constexpr quantity< volume_d >               quart_dry          { Rep( 1.101221e-3L ) * cube( meter ) };
+constexpr quantity< volume_d >               quart_liquid       { Rep( 9.463529e-4L ) * cube( meter ) };
+
+constexpr Rep                                revolution         { Rep( 2 ) * pi };
+constexpr quantity< dimensions< 1, -1, 1 > > rhe                { Rep( 1e+1L ) / pascal / second };
+constexpr quantity< length_d >               rod                { Rep( 5.029210L ) * meter };
+constexpr quantity< angular_velocity_d >     rpm                { Rep( 1.047198e-1L ) / second };
+
+constexpr quantity< time_interval_d >        second_sidereal    { Rep( 9.972696e-1L ) * second };
+constexpr quantity< time_interval_d >        shake              { Rep( 1e-8L ) * second };
+constexpr quantity< mass_d >                 slug               { Rep( 1.459390e+1L ) * kilogram };
+constexpr quantity< electric_current_d >     statampere         { Rep( 3.335641e-10L ) * ampere };
+constexpr quantity< electric_charge_d >      statcoulomb        { Rep( 3.335641e-10L ) * coulomb };
+constexpr quantity< capacitance_d >          statfarad          { Rep( 1.112650e-12L ) * farad };
+constexpr quantity< inductance_d >           stathenry          { Rep( 8.987552e+11L ) * henry };
+constexpr quantity< electric_conductance_d > statmho            { Rep( 1.112650e-12L ) * siemens };
+constexpr quantity< electric_resistance_d >  statohm            { Rep( 8.987552e+11L ) * ohm };
+constexpr quantity< electric_potential_d >   statvolt           { Rep( 2.997925e+2L ) * volt };
+constexpr quantity< volume_d >               stere              { cube( meter ) };
+constexpr quantity< illuminance_d >          stilb              { Rep( 1e+4L ) * candela / square( meter ) };
+constexpr quantity< kinematic_viscosity_d >  stokes             { Rep( 1e-4L ) * square( meter ) / second };
+
+constexpr quantity< volume_d >               tablespoon         { Rep( 1.478676e-5L ) * cube( meter ) };
+constexpr quantity< volume_d >               teaspoon           { Rep( 4.928922e-6L ) * cube( meter ) };
+constexpr quantity< dimensions< -1, 1, 0 > > tex                { Rep( 1e-6L ) * kilogram / meter };
+constexpr quantity< energy_d >               therm_ec           { Rep( 1.05506e+8L ) * joule };
+constexpr quantity< energy_d >               therm_us           { Rep( 1.054804e+8L ) * joule };
+constexpr quantity< mass_d >                 ton_assay          { Rep( 2.916667e-2L ) * kilogram };
+constexpr quantity< force_d >                ton_force          { Rep( 8.896443e+3L ) * newton };
+constexpr quantity< mass_d >                 ton_long           { Rep( 1.016047e+3L ) * kilogram };
+constexpr quantity< heat_flow_rate_d >       ton_refrigeration  { Rep( 3.516853e+3L ) * watt };
+constexpr quantity< volume_d >               ton_register       { Rep( 2.831685L ) * cube( meter ) };
+constexpr quantity< mass_d >                 ton_short          { Rep( 9.071847e+2L ) * kilogram };
+constexpr quantity< energy_d >               ton_tnt            { Rep( 4.184e+9L ) * joule };
+constexpr quantity< pressure_d >             torr               { Rep( 1.333224e+2L ) * pascal };
+
+constexpr quantity< magnetic_flux_d >        unit_pole          { Rep( 1.256637e-7L ) * weber };
+
+constexpr quantity< time_interval_d >        week               { Rep( 604800L ) * second }; // 7 days
+
+constexpr quantity< length_d >               x_unit             { Rep( 1.002e-13L ) * meter };
+
+constexpr quantity< length_d >               yard               { Rep( 9.144e-1L ) * meter };
+constexpr quantity< time_interval_d >        year_sidereal      { Rep( 3.155815e+7L ) * second };
+constexpr quantity< time_interval_d >        year_std           { Rep( 3.1536e+7L ) * second }; // 365 days
+constexpr quantity< time_interval_d >        year_tropical      { Rep( 3.155693e+7L ) * second };
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_OTHER_UNITS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/physical_constants.hpp b/third_party/phys/units/physical_constants.hpp
new file mode 100644
index 00000000..8a5669d5
--- /dev/null
+++ b/third_party/phys/units/physical_constants.hpp
@@ -0,0 +1,61 @@
+/**
+ * \file physical_constants.hpp
+ *
+ * \brief   Several physical constants.
+ * \author  Michael S. Kenniston, Martin Moene
+ * \date    7 September 2013
+ * \since   0.4
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ *
+ * Copyright (c) 2001 by Michael S. Kenniston.  For the most
+ * recent version check www.xnet.com/~msk/quantity.  Permission is granted
+ * to use this code without restriction so long as this copyright
+ * notice appears in all source files.
+ *
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_PHYSICAL_CONSTANTS_HPP_INCLUDED
+#define PHYS_UNITS_PHYSICAL_CONSTANTS_HPP_INCLUDED
+
+#include "phys/units/quantity.hpp"
+
+namespace phys { namespace units {
+
+// acceleration of free-fall, standard
+constexpr quantity< acceleration_d >
+                                g_sub_n { Rep( 9.80665L ) * meter / square( second ) };
+
+// Avogadro constant
+constexpr quantity< dimensions< 0, 0, 0, 0, 0, -1 > >
+                                N_sub_A { Rep( 6.02214199e+23L ) / mole };
+// electronvolt
+constexpr quantity< energy_d >  eV { Rep( 1.60217733e-19L ) * joule };
+
+// elementary charge
+constexpr quantity< electric_charge_d >
+                                e { Rep( 1.602176462e-19L ) * coulomb };
+
+// Planck constant
+constexpr quantity< dimensions< 2, 1, -1 > >
+                                h { Rep( 6.62606876e-34L ) * joule * second };
+
+// speed of light in a vacuum
+constexpr quantity< speed_d >   c { Rep( 299792458L ) * meter / second };
+
+// unified atomic mass unit
+constexpr quantity< mass_d >    u { Rep( 1.6605402e-27L ) * kilogram };
+
+// etc.
+
+}} // namespace phys { namespace units {
+
+#endif // PHYS_UNITS_PHYSICAL_CONSTANTS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity.hpp b/third_party/phys/units/quantity.hpp
new file mode 100644
index 00000000..d64e56bc
--- /dev/null
+++ b/third_party/phys/units/quantity.hpp
@@ -0,0 +1,967 @@
+/**
+ * \file quantity.hpp
+ *
+ * \brief   Zero-overhead dimensional analysis and unit/quantity manipulation and conversion.
+ * \author  Michael S. Kenniston, Martin Moene
+ * \date    7 September 2013
+ * \since   0.4
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ *
+ * Copyright (c) 2001 by Michael S. Kenniston.  For the most
+ * recent version check www.xnet.com/~msk/quantity.  Permission is granted
+ * to use this code without restriction so long as this copyright
+ * notice appears in all source files.
+ *
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * Unless otherwise specified, the definitions of all units in this
+ * file are from NIST Special Publication 811, found online at
+ * http://physics.nist.gov/Document/sp811.pdf
+ * Other sources: OED = Oxford English Dictionary
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_HPP_INCLUDED
+
+#include <cmath>
+#include <cstdlib>
+#include <utility>  // std::declval
+
+/// namespace phys.
+
+namespace phys {
+
+/// namespace units.
+
+namespace units {
+
+#ifdef PHYS_UNITS_REP_TYPE
+   using Rep = PHYS_UNITS_REP_TYPE;
+#else
+   using Rep = double;
+#endif
+
+/*
+ * declare now, define later.
+ */
+template< typename Dims, typename T = Rep >
+class quantity;
+
+/**
+ * We could drag dimensions around individually, but it's much more convenient to package them.
+ */
+template< int D1, int D2, int D3, int D4 = 0, int D5 = 0, int D6 = 0, int D7 = 0 >
+struct dimensions
+{
+    enum
+    {
+        dim1 = D1,
+        dim2 = D2,
+        dim3 = D3,
+        dim4 = D4,
+        dim5 = D5,
+        dim6 = D6,
+        dim7 = D7,
+
+        is_all_zero =
+            D1 == 0 && D2 == 0 && D3 == 0 && D4 == 0 && D5 == 0 && D6 == 0 && D7 == 0,
+
+        is_base =
+            1 == (D1 != 0) + (D2 != 0) + (D3 != 0) + (D4 != 0) + (D5 != 0) + (D6 != 0) + (D7 != 0)  &&
+            1 ==  D1 + D2 + D3 + D4 + D5 + D6 + D7,
+    };
+
+    template< int R1, int R2, int R3, int R4, int R5, int R6, int R7 >
+    constexpr bool operator==( dimensions<R1, R2, R3, R4, R5, R6, R7> const & ) const
+    {
+        return D1==R1 && D2==R2 && D3==R3 && D4==R4 && D5==R5 && D6==R6 && D7==R7;
+    }
+
+    template< int R1, int R2, int R3, int R4, int R5, int R6, int R7 >
+    constexpr bool operator!=( dimensions<R1, R2, R3, R4, R5, R6, R7> const & rhs ) const
+    {
+        return !( *this == rhs );
+    }
+};
+
+/// demensionless 'dimension'.
+
+typedef dimensions< 0, 0, 0 > dimensionless_d;
+
+/// namespace detail.
+
+namespace detail {
+
+/**
+ * \brief The "collapse" template is used to avoid quantity< dimensions< 0, 0, 0 > >,
+ * i.e. to make dimensionless results come out as type "Rep".
+ */
+template< typename D, typename T >
+struct collapse
+{
+    typedef quantity< D, T > type;
+};
+
+template< typename T >
+struct collapse< dimensionless_d, T >
+{
+    typedef T type;
+};
+
+template< typename D, typename T >
+using Collapse = typename collapse<D,T>::type;
+
+// promote types of expression to result type.
+
+template < typename X, typename Y >
+using PromoteAdd = decltype( std::declval<X>() + std::declval<Y>() );
+
+template < typename X, typename Y >
+using PromoteMul = decltype( std::declval<X>() * std::declval<Y>() );
+
+/*
+ * The following batch of structs are type generators to calculate
+ * the correct type of the result of various operations.
+ */
+
+/**
+ * product type generator.
+ */
+template< typename DX, typename DY, typename T >
+struct product
+{
+    enum
+    {
+        d1 = DX::dim1 + DY::dim1,
+        d2 = DX::dim2 + DY::dim2,
+        d3 = DX::dim3 + DY::dim3,
+        d4 = DX::dim4 + DY::dim4,
+        d5 = DX::dim5 + DY::dim5,
+        d6 = DX::dim6 + DY::dim6,
+        d7 = DX::dim7 + DY::dim7,
+    };
+
+    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
+};
+
+template< typename DX, typename DY, typename X, typename Y>
+using Product = typename product<DX, DY, PromoteMul<X,Y>>::type;
+
+/**
+ * quotient type generator.
+ */
+template< typename DX, typename DY, typename T >
+struct quotient
+{
+    enum
+    {
+        d1 = DX::dim1 - DY::dim1,
+        d2 = DX::dim2 - DY::dim2,
+        d3 = DX::dim3 - DY::dim3,
+        d4 = DX::dim4 - DY::dim4,
+        d5 = DX::dim5 - DY::dim5,
+        d6 = DX::dim6 - DY::dim6,
+        d7 = DX::dim7 - DY::dim7,
+    };
+
+    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
+};
+
+template< typename DX, typename DY, typename X, typename Y>
+using Quotient = typename quotient<DX, DY, PromoteMul<X,Y>>::type;
+
+/**
+ * reciprocal type generator.
+ */
+template< typename D, typename T >
+struct reciprocal
+{
+    enum
+    {
+        d1 = - D::dim1,
+        d2 = - D::dim2,
+        d3 = - D::dim3,
+        d4 = - D::dim4,
+        d5 = - D::dim5,
+        d6 = - D::dim6,
+        d7 = - D::dim7,
+    };
+
+    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
+};
+
+template< typename D, typename X, typename Y>
+using Reciprocal = typename reciprocal<D, PromoteMul<X,Y>>::type;
+
+/**
+ * power type generator.
+ */
+template< typename D, int N, typename T >
+struct power
+{
+    enum
+    {
+        d1 = N * D::dim1,
+        d2 = N * D::dim2,
+        d3 = N * D::dim3,
+        d4 = N * D::dim4,
+        d5 = N * D::dim5,
+        d6 = N * D::dim6,
+        d7 = N * D::dim7,
+    };
+
+    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
+};
+
+template< typename D, int N, typename T >
+using Power = typename detail::power< D, N, T >::type;
+
+/**
+ * root type generator.
+ */
+template< typename D, int N, typename T >
+struct root
+{
+    enum
+    {
+        all_even_multiples =
+            D::dim1 % N == 0 &&
+            D::dim2 % N == 0 &&
+            D::dim3 % N == 0 &&
+            D::dim4 % N == 0 &&
+            D::dim5 % N == 0 &&
+            D::dim6 % N == 0 &&
+            D::dim7 % N == 0
+    };
+
+    enum
+    {
+        d1 = D::dim1 / N,
+        d2 = D::dim2 / N,
+        d3 = D::dim3 / N,
+        d4 = D::dim4 / N,
+        d5 = D::dim5 / N,
+        d6 = D::dim6 / N,
+        d7 = D::dim7 / N
+    };
+
+    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
+};
+
+template< typename D, int N, typename T >
+using Root = typename detail::root< D, N, T >::type;
+
+/**
+ * tag to construct a quantity from a magnitude.
+ */
+constexpr struct magnitude_tag_t{} magnitude_tag{};
+
+} // namespace detail
+
+/**
+ * \brief class "quantity" is the heart of the library. It associates
+ * dimensions  with a single "Rep" data member and protects it from
+ * dimensionally inconsistent use.
+ */
+template< typename Dims, typename T /*= Rep */ >
+class quantity
+{
+public:
+    typedef Dims dimension_type;
+
+    typedef T value_type;
+
+    typedef quantity<Dims, T> this_type;
+
+    constexpr quantity() : m_value{} { }
+
+    /**
+     * public converting initializing constructor;
+     * requires magnitude_tag to prevent constructing a quantity from a raw magnitude.
+     */
+    template <typename X>
+    constexpr explicit quantity( detail::magnitude_tag_t, X x )
+    : m_value( x ) { }
+
+    /**
+     * converting copy-assignment constructor.
+     */
+    template <typename X >
+    constexpr quantity( quantity<Dims, X> const & x )
+    : m_value( x.magnitude() ) { }
+
+//    /**
+//     * convert to compatible unit, for example: (3._dm).to(meter) gives 0.3;
+//     */
+//    constexpr value_type to( quantity const & x ) const {  return *this / x; }
+
+    /**
+     * convert to given unit, for example: (3._dm).to(meter) gives 0.3;
+     */
+    template <typename DX, typename X>
+    constexpr auto to( quantity<DX,X> const & x ) const -> detail::Quotient<Dims,DX,T,X>
+    {
+        return *this / x;
+    }
+
+    /**
+     * the quantity's magnitude.
+     */
+    constexpr value_type magnitude() const { return m_value; }
+
+    /**
+     * the quantity's dimensions.
+     */
+    constexpr dimension_type dimension() const { return dimension_type{}; }
+
+    /**
+     * We need a "zero" of each type -- for comparisons, to initialize running
+     * totals, etc.  Note:  0 m != 0 kg, since they are of different dimensionality.
+     * zero is really just defined for convenience, since
+     * quantity< length_d >::zero == 0 * meter, etc.
+     */
+    static constexpr quantity zero() { return quantity{ value_type( 0.0 ) }; }
+//    static constexpr quantity zero = quantity{ value_type( 0.0 ) };
+
+private:
+    /**
+     * private initializing constructor.
+     */
+    constexpr explicit quantity( value_type x ) : m_value{ x } { }
+
+private:
+    value_type m_value;
+
+    enum { has_dimension = ! Dims::is_all_zero };
+
+    static_assert( has_dimension, "quantity dimensions must not all be zero" );
+
+private:
+    // friends:
+
+    // arithmetic
+
+    template <typename D, typename X, typename Y>
+    friend constexpr quantity<D, X> &
+    operator+=( quantity<D, X> & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X>
+    friend constexpr quantity<D, X>
+    operator+( quantity<D, X> const & x );
+
+    template< typename D, typename X, typename Y >
+    friend constexpr quantity <D, detail::PromoteAdd<X,Y>>
+    operator+( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr quantity<D, X> &
+    operator-=( quantity<D, X> & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X>
+    friend constexpr quantity<D, X>
+    operator-( quantity<D, X> const & x );
+
+    template< typename D, typename X, typename Y >
+    friend constexpr quantity <D, detail::PromoteAdd<X,Y>>
+    operator-( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template< typename D, typename X, typename Y>
+    friend constexpr quantity<D, X> &
+    operator*=( quantity<D, X> & x, const Y & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr quantity<D, detail::PromoteMul<X,Y>>
+    operator*( quantity<D, X> const & x, const Y & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr quantity< D, detail::PromoteMul<X,Y> >
+    operator*( const X & x, quantity<D, Y> const & y );
+
+    template <typename DX, typename DY, typename X, typename Y>
+    friend constexpr detail::Product<DX, DY, X, Y>
+    operator*( quantity<DX, X> const & lhs, quantity< DY, Y > const & rhs );
+
+    template< typename D, typename X, typename Y>
+    friend constexpr quantity<D, X> &
+    operator/=( quantity<D, X> & x, const Y & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr quantity<D, detail::PromoteMul<X,Y>>
+    operator/( quantity<D, X> const & x, const Y & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr detail::Reciprocal<D, X, Y>
+    operator/( const X & x, quantity<D, Y> const & y );
+
+    template <typename DX, typename DY, typename X, typename Y>
+    friend constexpr detail::Quotient<DX, DY, X, Y>
+    operator/( quantity<DX, X> const & x, quantity< DY, Y > const & y );
+
+    // absolute value.
+
+    template <typename D, typename X>
+    friend constexpr quantity<D,X>
+    abs( quantity<D,X> const & x );
+
+    // powers and roots
+
+    template <int N, typename D, typename X>
+    friend detail::Power<D, N, X>
+    nth_power( quantity<D, X> const & x );
+
+    template <typename D, typename X>
+    friend constexpr detail::Power<D, 2, X>
+    square( quantity<D, X> const & x );
+
+    template <typename D, typename X>
+    friend constexpr detail::Power<D, 3, X>
+    cube( quantity<D, X> const & x );
+
+    template <int N, typename D, typename X>
+    friend detail::Root<D, N, X>
+    nth_root( quantity<D, X> const & x );
+
+    template <typename D, typename X>
+    friend detail::Root< D, 2, X >
+    sqrt( quantity<D, X> const & x );
+
+    // comparison
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator==( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator!=( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator<( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator<=( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator>( quantity<D, X> const & x, quantity<D, Y> const & y );
+
+    template <typename D, typename X, typename Y>
+    friend constexpr bool operator>=( quantity<D, X> const & x, quantity<D, Y> const & y );
+};
+
+// Give names to the seven fundamental dimensions of physical reality.
+
+typedef dimensions< 1, 0, 0, 0, 0, 0, 0 > length_d;
+typedef dimensions< 0, 1, 0, 0, 0, 0, 0 > mass_d;
+typedef dimensions< 0, 0, 1, 0, 0, 0, 0 > time_interval_d;
+typedef dimensions< 0, 0, 0, 1, 0, 0, 0 > electric_current_d;
+typedef dimensions< 0, 0, 0, 0, 1, 0, 0 > thermodynamic_temperature_d;
+typedef dimensions< 0, 0, 0, 0, 0, 1, 0 > amount_of_substance_d;
+typedef dimensions< 0, 0, 0, 0, 0, 0, 1 > luminous_intensity_d;
+
+// Addition operators
+
+/// quan += quan
+
+template <typename D, typename X, typename Y>
+constexpr quantity<D, X> &
+operator+=( quantity<D, X> & x, quantity<D, Y> const & y )
+{
+    return x.m_value += y.m_value, x;
+}
+
+/// + quan
+
+template <typename D, typename X>
+constexpr quantity<D, X>
+operator+( quantity<D, X> const & x )
+{
+   return quantity<D, X >( +x.m_value );
+}
+
+/// quan + quan
+
+template< typename D, typename X, typename Y >
+constexpr quantity <D, detail::PromoteAdd<X,Y>>
+operator+( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return quantity<D, detail::PromoteAdd<X,Y>>( x.m_value + y.m_value );
+}
+
+// Subtraction operators
+
+/// quan -= quan
+
+template <typename D, typename X, typename Y>
+constexpr quantity<D, X> &
+operator-=( quantity<D, X> & x, quantity<D, Y> const & y )
+{
+    return x.m_value -= y.m_value, x;
+}
+
+/// - quan
+
+template <typename D, typename X>
+constexpr quantity<D, X>
+operator-( quantity<D, X> const & x )
+{
+   return quantity<D, X >( -x.m_value );
+}
+
+/// quan - quan
+
+template< typename D, typename X, typename Y >
+constexpr quantity <D, detail::PromoteAdd<X,Y>>
+operator-( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return quantity<D, detail::PromoteAdd<X,Y>>( x.m_value - y.m_value );
+}
+
+// Multiplication operators
+
+/// quan *= num
+
+template< typename D, typename X, typename Y>
+constexpr quantity<D, X> &
+operator*=( quantity<D, X> & x, const Y & y )
+{
+   return x.m_value *= y, x;
+}
+
+/// quan * num
+
+template <typename D, typename X, typename Y>
+constexpr quantity<D, detail::PromoteMul<X,Y>>
+operator*( quantity<D, X> const & x, const Y & y )
+{
+   return quantity<D, detail::PromoteMul<X,Y>>( x.m_value * y );
+}
+
+/// num * quan
+
+template <typename D, typename X, typename Y>
+constexpr quantity< D, detail::PromoteMul<X,Y> >
+operator*( const X & x, quantity<D, Y> const & y )
+{
+   return quantity<D, detail::PromoteMul<X,Y>>( x * y.m_value );
+}
+
+/// quan * quan:
+
+template <typename DX, typename DY, typename X, typename Y>
+constexpr detail::Product<DX, DY, X, Y>
+operator*( quantity<DX, X> const & lhs, quantity< DY, Y > const & rhs )
+{
+    return detail::Product<DX, DY, X, Y>( lhs.m_value * rhs.m_value );
+}
+
+// Division operators
+
+/// quan /= num
+
+template< typename D, typename X, typename Y>
+constexpr quantity<D, X> &
+operator/=( quantity<D, X> & x, const Y & y )
+{
+   return x.m_value /= y, x;
+}
+
+/// quan / num
+
+template <typename D, typename X, typename Y>
+constexpr quantity<D, detail::PromoteMul<X,Y>>
+operator/( quantity<D, X> const & x, const Y & y )
+{
+   return quantity<D, detail::PromoteMul<X,Y>>( x.m_value / y );
+}
+
+/// num / quan
+
+template <typename D, typename X, typename Y>
+constexpr detail::Reciprocal<D, X, Y>
+operator/( const X & x, quantity<D, Y> const & y )
+{
+   return detail::Reciprocal<D, X, Y>( x / y.m_value );
+}
+
+/// quan / quan:
+
+template <typename DX, typename DY, typename X, typename Y>
+constexpr detail::Quotient<DX, DY, X, Y>
+operator/( quantity<DX, X> const & x, quantity< DY, Y > const & y )
+{
+    return detail::Quotient<DX, DY, X, Y>( x.m_value / y.m_value );
+}
+
+/// absolute value.
+
+template <typename D, typename X>
+constexpr quantity<D,X> abs( quantity<D,X> const & x )
+{
+   return quantity<D,X>( std::abs( x.m_value ) );
+}
+
+// General powers
+
+/// N-th power.
+
+template <int N, typename D, typename X>
+detail::Power<D, N, X>
+nth_power( quantity<D, X> const & x )
+{
+   return detail::Power<D, N, X>( std::pow( x.m_value, X( N ) ) );
+}
+
+// Low powers defined separately for efficiency.
+
+/// square.
+
+template <typename D, typename X>
+constexpr detail::Power<D, 2, X>
+square( quantity<D, X> const & x )
+{
+   return x * x;
+}
+
+/// cube.
+
+template <typename D, typename X>
+constexpr detail::Power<D, 3, X>
+cube( quantity<D, X> const & x )
+{
+   return x * x * x;
+}
+
+// General root
+
+/// n-th root.
+
+template <int N, typename D, typename X>
+detail::Root<D, N, X>
+nth_root( quantity<D, X> const & x )
+{
+   static_assert( detail::root<D, N, X>::all_even_multiples, "root result dimensions must be integral" );
+
+   return detail::Root<D, N, X>( std::pow( x.m_value, X( 1.0 ) / N ) );
+}
+
+// Low roots defined separately for convenience.
+
+/// square root.
+
+template <typename D, typename X>
+detail::Root< D, 2, X >
+sqrt( quantity<D, X> const & x )
+{
+   static_assert(
+      detail::root<D, 2, X >::all_even_multiples, "root result dimensions must be integral" );
+
+   return detail::Root<D, 2, X>( std::pow( x.m_value, X( 1.0 ) / 2 ) );
+}
+
+// Comparison operators
+
+/// equality.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator==( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value == y.m_value;
+}
+
+/// inequality.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator!=( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value != y.m_value;
+}
+
+/// less-than.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator<( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value < y.m_value;
+}
+
+/// less-equal.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator<=( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value <= y.m_value;
+}
+
+/// greater-than.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator>( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value > y.m_value;
+}
+
+/// greater-equal.
+
+template <typename D, typename X, typename Y>
+constexpr bool
+operator>=( quantity<D, X> const & x, quantity<D, Y> const & y )
+{
+   return x.m_value >= y.m_value;
+}
+
+/// quantity's dimension.
+
+template <typename DX, typename X>
+inline constexpr DX dimension( quantity<DX,X> const & q ) { return q.dimension(); }
+
+/// quantity's magnitude.
+
+template <typename DX, typename X>
+inline constexpr X magnitude( quantity<DX,X> const & q ) { return q.magnitude(); }
+
+// The seven SI base units.  These tie our numbers to the real world.
+
+constexpr quantity<length_d                   > meter   { detail::magnitude_tag, 1.0 };
+constexpr quantity<mass_d                     > kilogram{ detail::magnitude_tag, 1.0 };
+constexpr quantity<time_interval_d            > second  { detail::magnitude_tag, 1.0 };
+constexpr quantity<electric_current_d         > ampere  { detail::magnitude_tag, 1.0 };
+constexpr quantity<thermodynamic_temperature_d> kelvin  { detail::magnitude_tag, 1.0 };
+constexpr quantity<amount_of_substance_d      > mole    { detail::magnitude_tag, 1.0 };
+constexpr quantity<luminous_intensity_d       > candela { detail::magnitude_tag, 1.0 };
+
+// The standard SI prefixes.
+
+constexpr long double yotta = 1e+24L;
+constexpr long double zetta = 1e+21L;
+constexpr long double   exa = 1e+18L;
+constexpr long double  peta = 1e+15L;
+constexpr long double  tera = 1e+12L;
+constexpr long double  giga = 1e+9L;
+constexpr long double  mega = 1e+6L;
+constexpr long double  kilo = 1e+3L;
+constexpr long double hecto = 1e+2L;
+constexpr long double  deka = 1e+1L;
+constexpr long double  deci = 1e-1L;
+constexpr long double centi = 1e-2L;
+constexpr long double milli = 1e-3L;
+constexpr long double micro = 1e-6L;
+constexpr long double  nano = 1e-9L;
+constexpr long double  pico = 1e-12L;
+constexpr long double femto = 1e-15L;
+constexpr long double  atto = 1e-18L;
+constexpr long double zepto = 1e-21L;
+constexpr long double yocto = 1e-24L;
+
+// Binary prefixes, pending adoption.
+
+constexpr long double kibi = 1024;
+constexpr long double mebi = 1024 * kibi;
+constexpr long double gibi = 1024 * mebi;
+constexpr long double tebi = 1024 * gibi;
+constexpr long double pebi = 1024 * tebi;
+constexpr long double exbi = 1024 * pebi;
+constexpr long double zebi = 1024 * exbi;
+constexpr long double yobi = 1024 * zebi;
+
+// The rest of the standard dimensional types, as specified in SP811.
+
+using absorbed_dose_d             = dimensions< 2, 0, -2 >;
+using absorbed_dose_rate_d        = dimensions< 2, 0, -3 >;
+using acceleration_d              = dimensions< 1, 0, -2 >;
+using activity_of_a_nuclide_d     = dimensions< 0, 0, -1 >;
+using angular_velocity_d          = dimensions< 0, 0, -1 >;
+using angular_acceleration_d      = dimensions< 0, 0, -2 >;
+using area_d                      = dimensions< 2, 0, 0 >;
+using capacitance_d               = dimensions< -2, -1, 4, 2 >;
+using concentration_d             = dimensions< -3, 0, 0, 0, 0, 1 >;
+using current_density_d           = dimensions< -2, 0, 0, 1 >;
+using dose_equivalent_d           = dimensions< 2, 0, -2 >;
+using dynamic_viscosity_d         = dimensions< -1, 1, -1 >;
+using electric_charge_d           = dimensions< 0, 0, 1, 1 >;
+using electric_charge_density_d   = dimensions< -3, 0, 1, 1 >;
+using electric_conductance_d      = dimensions< -2, -1, 3, 2 >;
+using electric_field_strenth_d    = dimensions< 1, 1, -3, -1 >;
+using electric_flux_density_d     = dimensions< -2, 0, 1, 1 >;
+using electric_potential_d        = dimensions< 2, 1, -3, -1 >;
+using electric_resistance_d       = dimensions< 2, 1, -3, -2 >;
+using energy_d                    = dimensions< 2, 1, -2 >;
+using energy_density_d            = dimensions< -1, 1, -2 >;
+using exposure_d                  = dimensions< 0, -1, 1, 1 >;
+using force_d                     = dimensions< 1, 1, -2 >;
+using frequency_d                 = dimensions< 0, 0, -1 >;
+using heat_capacity_d             = dimensions< 2, 1, -2, 0, -1 >;
+using heat_density_d              = dimensions< 0, 1, -2 >;
+using heat_density_flow_rate_d    = dimensions< 0, 1, -3 >;
+using heat_flow_rate_d            = dimensions< 2, 1, -3 >;
+using heat_flux_density_d         = dimensions< 0, 1, -3 >;
+using heat_transfer_coefficient_d = dimensions< 0, 1, -3, 0, -1 >;
+using illuminance_d               = dimensions< -2, 0, 0, 0, 0, 0, 1 >;
+using inductance_d                = dimensions< 2, 1, -2, -2 >;
+using irradiance_d                = dimensions< 0, 1, -3 >;
+using kinematic_viscosity_d       = dimensions< 2, 0, -1 >;
+using luminance_d                 = dimensions< -2, 0, 0, 0, 0, 0, 1 >;
+using luminous_flux_d             = dimensions< 0, 0, 0, 0, 0, 0, 1 >;
+using magnetic_field_strength_d   = dimensions< -1, 0, 0, 1 >;
+using magnetic_flux_d             = dimensions< 2, 1, -2, -1 >;
+using magnetic_flux_density_d     = dimensions< 0, 1, -2, -1 >;
+using magnetic_permeability_d     = dimensions< 1, 1, -2, -2 >;
+using mass_density_d              = dimensions< -3, 1, 0 >;
+using mass_flow_rate_d            = dimensions< 0, 1, -1 >;
+using molar_energy_d              = dimensions< 2, 1, -2, 0, 0, -1 >;
+using molar_entropy_d             = dimensions< 2, 1, -2, -1, 0, -1 >;
+using moment_of_force_d           = dimensions< 2, 1, -2 >;
+using permittivity_d              = dimensions< -3, -1, 4, 2 >;
+using power_d                     = dimensions< 2, 1, -3 >;
+using pressure_d                  = dimensions< -1, 1, -2 >;
+using radiance_d                  = dimensions< 0, 1, -3 >;
+using radiant_intensity_d         = dimensions< 2, 1, -3 >;
+using speed_d                     = dimensions< 1, 0, -1 >;
+using specific_energy_d           = dimensions< 2, 0, -2 >;
+using specific_heat_capacity_d    = dimensions< 2, 0, -2, 0, -1 >;
+using specific_volume_d           = dimensions< 3, -1, 0 >;
+using substance_permeability_d    = dimensions< -1, 0, 1 >;
+using surface_tension_d           = dimensions< 0, 1, -2 >;
+using thermal_conductivity_d      = dimensions< 1, 1, -3, 0, -1 >;
+using thermal_diffusivity_d       = dimensions< 2, 0, -1 >;
+using thermal_insulance_d         = dimensions< 0, -1, 3, 0, 1 >;
+using thermal_resistance_d        = dimensions< -2, -1, 3, 0, 1 >;
+using thermal_resistivity_d       = dimensions< -1, -1, 3, 0, 1 >;
+using torque_d                    = dimensions< 2, 1, -2 >;
+using volume_d                    = dimensions< 3, 0, 0 >;
+using volume_flow_rate_d          = dimensions< 3, 0, -1 >;
+using wave_number_d               = dimensions< -1, 0, 0 >;
+
+// Handy values.
+
+constexpr Rep pi      { Rep( 3.141592653589793238462L ) };
+constexpr Rep percent { Rep( 1 ) / 100 };
+
+//// Not approved for use alone, but needed for use with prefixes.
+constexpr quantity< mass_d                  > gram         { kilogram / 1000 };
+
+// The derived SI units, as specified in SP811.
+
+constexpr Rep                                 radian       { Rep( 1 ) };
+constexpr Rep                                 steradian    { Rep( 1 ) };
+constexpr quantity< force_d                 > newton       { meter * kilogram / square( second ) };
+constexpr quantity< pressure_d              > pascal       { newton / square( meter ) };
+constexpr quantity< energy_d                > joule        { newton * meter };
+constexpr quantity< power_d                 > watt         { joule / second };
+constexpr quantity< electric_charge_d       > coulomb      { second * ampere };
+constexpr quantity< electric_potential_d    > volt         { watt / ampere };
+constexpr quantity< capacitance_d           > farad        { coulomb / volt };
+constexpr quantity< electric_resistance_d   > ohm          { volt / ampere };
+constexpr quantity< electric_conductance_d  > siemens      { ampere / volt };
+constexpr quantity< magnetic_flux_d         > weber        { volt * second };
+constexpr quantity< magnetic_flux_density_d > tesla        { weber / square( meter ) };
+constexpr quantity< inductance_d            > henry        { weber / ampere };
+constexpr quantity< thermodynamic_temperature_d > degree_celsius   { kelvin };
+constexpr quantity< luminous_flux_d         > lumen        { candela * steradian };
+constexpr quantity< illuminance_d           > lux          { lumen / meter / meter };
+constexpr quantity< activity_of_a_nuclide_d > becquerel    { 1 / second };
+constexpr quantity< absorbed_dose_d         > gray         { joule / kilogram };
+constexpr quantity< dose_equivalent_d       > sievert      { joule / kilogram };
+constexpr quantity< frequency_d             > hertz        { 1 / second };
+
+// The rest of the units approved for use with SI, as specified in SP811.
+// (However, use of these units is generally discouraged.)
+
+constexpr quantity< length_d                > angstrom     { Rep( 1e-10L ) * meter };
+constexpr quantity< area_d                  > are          { Rep( 1e+2L ) * square( meter ) };
+constexpr quantity< pressure_d              > bar          { Rep( 1e+5L ) * pascal };
+constexpr quantity< area_d                  > barn         { Rep( 1e-28L ) * square( meter ) };
+constexpr quantity< activity_of_a_nuclide_d > curie        { Rep( 3.7e+10L ) * becquerel };
+constexpr quantity< time_interval_d         > day          { Rep( 86400L ) * second };
+constexpr Rep                                 degree_angle { pi / 180 };
+constexpr quantity< acceleration_d          > gal          { Rep( 1e-2L ) * meter / square( second ) };
+constexpr quantity< area_d                  > hectare      { Rep( 1e+4L ) * square( meter ) };
+constexpr quantity< time_interval_d         > hour         { Rep( 3600 ) * second };
+constexpr quantity< speed_d                 > knot         { Rep( 1852 ) / 3600 * meter / second };
+constexpr quantity< volume_d                > liter        { Rep( 1e-3L ) * cube( meter ) };
+constexpr quantity< time_interval_d         > minute       { Rep( 60 ) * second };
+constexpr Rep                                 minute_angle { pi / 10800 };
+constexpr quantity< length_d                > mile_nautical{ Rep( 1852 ) * meter };
+constexpr quantity< absorbed_dose_d         > rad          { Rep( 1e-2L ) * gray };
+constexpr quantity< dose_equivalent_d       > rem          { Rep( 1e-2L ) * sievert };
+constexpr quantity< exposure_d              > roentgen     { Rep( 2.58e-4L ) * coulomb / kilogram };
+constexpr Rep                                 second_angle { pi / 648000L };
+constexpr quantity< mass_d                  > ton_metric   { Rep( 1e+3L ) * kilogram };
+
+// Alternate (non-US) spellings:
+
+constexpr quantity< length_d                > metre        { meter };
+constexpr quantity< volume_d                > litre        { liter };
+constexpr Rep                                 deca         { deka };
+constexpr quantity< mass_d                  > tonne        { ton_metric };
+
+// cooked literals for base units;
+// these could also have been created with a script.
+
+#define QUANTITY_DEFINE_SCALING_LITERAL( sfx, dim, factor ) \
+    constexpr quantity<dim, double> operator "" _ ## sfx(unsigned long long x) \
+    { \
+        return quantity<dim, double>( detail::magnitude_tag, factor * x ); \
+    } \
+    constexpr quantity<dim, double> operator "" _ ## sfx(long double x) \
+    { \
+        return quantity<dim, double>( detail::magnitude_tag, factor * x ); \
+    }
+
+#define QUANTITY_DEFINE_SCALING_LITERALS( pfx, dim, fact ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( Y ## pfx, dim, fact * yotta ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( Z ## pfx, dim, fact * zetta ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( E ## pfx, dim, fact * exa   ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( P ## pfx, dim, fact * peta  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( T ## pfx, dim, fact * tera  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( G ## pfx, dim, fact * giga  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( M ## pfx, dim, fact * mega  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( k ## pfx, dim, fact * kilo  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( h ## pfx, dim, fact * hecto ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( da## pfx, dim, fact * deka  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL(      pfx, dim, fact * 1     ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( d ## pfx, dim, fact * deci  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( c ## pfx, dim, fact * centi ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( m ## pfx, dim, fact * milli ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( u ## pfx, dim, fact * micro ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( n ## pfx, dim, fact * nano  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( p ## pfx, dim, fact * pico  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( f ## pfx, dim, fact * femto ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( a ## pfx, dim, fact * atto  ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( z ## pfx, dim, fact * zepto ) \
+    QUANTITY_DEFINE_SCALING_LITERAL( y ## pfx, dim, fact * yocto )
+
+
+#define QUANTITY_DEFINE_LITERALS( pfx, dim ) \
+    QUANTITY_DEFINE_SCALING_LITERALS( pfx, dim, 1 )
+
+/// literals
+
+namespace literals {
+
+QUANTITY_DEFINE_SCALING_LITERALS( g, mass_d, 1e-3 )
+
+QUANTITY_DEFINE_LITERALS( m  , length_d )
+QUANTITY_DEFINE_LITERALS( s  , time_interval_d )
+QUANTITY_DEFINE_LITERALS( A  , electric_current_d )
+QUANTITY_DEFINE_LITERALS( K  , thermodynamic_temperature_d )
+QUANTITY_DEFINE_LITERALS( mol, amount_of_substance_d )
+QUANTITY_DEFINE_LITERALS( cd , luminous_intensity_d )
+
+} // namespace literals
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io.hpp b/third_party/phys/units/quantity_io.hpp
new file mode 100644
index 00000000..75df1ba6
--- /dev/null
+++ b/third_party/phys/units/quantity_io.hpp
@@ -0,0 +1,251 @@
+/**
+ * \file quantity_io.hpp
+ *
+ * \brief   IO for quantity library.
+ * \author  Michael S. Kenniston, Martin Moene
+ * \date    10 September 2013
+ * \since   0.4
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ *
+ * Copyright (c) 2001 by Michael S. Kenniston.  For the most
+ * recent version check www.xnet.com/~msk/quantity.  Permission is granted
+ * to use this code without restriction so long as this copyright
+ * notice appears in all source files.
+ *
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
+
+#include "phys/units/quantity.hpp"
+
+#include <algorithm>
+#include <iosfwd>
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <sstream>
+
+/// namespace phys.
+
+namespace phys {
+
+/// namespace units.
+
+namespace units {
+
+/// quantity error base class (not used by quantity itself).
+
+struct quantity_error : public std::runtime_error
+{
+    quantity_error( std::string const text )
+        : std::runtime_error( text )  { }
+};
+
+/// prefix error, e.g. when prefix is unrecognized.
+
+struct prefix_error : public quantity_error
+{
+    prefix_error( std::string const text )
+        : quantity_error( text ) { }
+};
+
+/// return factor for given prefix.
+
+inline Rep prefix( std::string const prefix_ )
+{
+    std::map<std::string, Rep> table
+    {
+        { "m", milli },
+        { "k", kilo  },
+        { "u", micro },
+        { "M", mega  },
+        { "n", nano  },
+        { "G", giga  },
+        { "p", pico  },
+        { "T", tera  },
+        { "f", femto },
+        { "P", peta  },
+        { "a", atto  },
+        { "E", exa   },
+        { "z", zepto },
+        { "Z", zetta },
+        { "y", yocto },
+        { "Y", yotta },
+        { "h", hecto },
+        { "da", deka },
+        { "d", deci  },
+        { "c", centi },
+    };
+
+    auto pos = table.find( prefix_ );
+
+    if ( pos == table.end() )
+    {
+        throw prefix_error( "quantity: unrecognized prefix '" + prefix_ + "'" );
+    }
+
+    return pos->second;
+}
+
+/**
+ * Provide SI units-and-exponents in as close to NIST-specified format as possible with plain ascii.
+ *
+ * Made presentation customizable by specialization of template.
+ * Adapted by Martin Moene, 21 February 2012.
+ */
+template <typename Dims>
+struct unit_info
+{
+    /// true if base dimension.
+
+    static bool single()
+    {
+        return Dims::is_base;
+    }
+
+    /// provide unit's name.
+
+    static std::string name()
+    {
+        return symbol();
+    }
+
+    /// provide unit's symbol.
+
+    static std::string symbol()
+    {
+        std::ostringstream os;
+
+        bool first = true;
+
+        emit_dim( os, "m",   Dims::dim1, first );
+        emit_dim( os, "kg",  Dims::dim2, first );
+        emit_dim( os, "s",   Dims::dim3, first );
+        emit_dim( os, "A",   Dims::dim4, first );
+        emit_dim( os, "K",   Dims::dim5, first );
+        emit_dim( os, "mol", Dims::dim6, first );
+        emit_dim( os, "cd",  Dims::dim7, first );
+
+        return os.str();
+    }
+
+    /// emit a single dimension.
+
+    static void emit_dim( std::ostream & os, const char * label, int exp, bool & first )
+    {
+        if( exp == 0 )
+            return;
+
+        if ( first )
+            first = false;
+        else
+            os << " ";
+
+        os << label;
+
+        if( exp > 1 )
+            os << "+";
+
+        if( exp != 1 )
+            os << exp;
+    }
+};
+
+}} // namespace phys::units
+
+#include "quantity_io_meter.hpp"
+#include "quantity_io_kilogram.hpp"
+#include "quantity_io_second.hpp"
+#include "quantity_io_ampere.hpp"
+#include "quantity_io_mole.hpp"
+#include "quantity_io_candela.hpp"
+
+/*
+ * User must choose celsius or kelvin, either by defining
+ * QUANTITY_USE_CELSIUS or QUANTITY_USE_KELVIN, or by
+ * including the desired include file.
+ */
+#if defined(QUANTITY_USE_CELSIUS) && defined(QUANTITY_USE_KELVIN)
+# error At most define one of QUANTITY_USE_CELSIUS, QUANTITY_USE_KELVIN
+#endif
+#ifdef QUANTITY_USE_CELSIUS
+# include "quantity_io_celsius.hpp"
+#endif
+#ifdef QUANTITY_USE_KELVIN
+# include "quantity_io_kelvin.hpp"
+#endif
+
+namespace phys { namespace units {
+
+/// magnitude as string.
+
+template< typename  Dims, typename T >
+std::string to_magnitude( quantity<Dims, T> const & q )
+{
+    std::ostringstream os;
+    os << q.magnitude();
+    return os.str();
+}
+
+/// unit name.
+
+template< typename Dims, typename T >
+std::string to_unit_name( quantity<Dims, T> const & /* q  */)
+{
+    return unit_info<Dims>::name();
+}
+
+/// unit symbol.
+
+template< typename Dims, typename T >
+std::string to_unit_symbol( quantity<Dims, T> const & /* q */)
+{
+    return unit_info<Dims>::symbol();
+}
+
+/// string representation of value.
+
+inline std::string to_string( long double const value )
+{
+    std::ostringstream os;
+    os << value;
+    return os.str();
+}
+
+/// namespace io.
+
+namespace io {
+
+/// stream quantity.
+
+template< typename Dims, typename T >
+std::ostream & operator<<( std::ostream & os, quantity<Dims, T> const & q )
+{
+    return os << q.magnitude() << " " << to_unit_symbol( q );
+}
+
+/// quantity string representation.
+
+template< typename Dims, typename T >
+std::string to_string( quantity<Dims, T> const & q )
+{
+    std::ostringstream os;
+    os << q;
+    return os.str();
+}
+
+} // namespace io
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_ampere.hpp b/third_party/phys/units/quantity_io_ampere.hpp
new file mode 100644
index 00000000..a21e8c25
--- /dev/null
+++ b/third_party/phys/units/quantity_io_ampere.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_ampere.hpp
+ *
+ * \brief   ampere, electrical current, a fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_AMPERE_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_AMPERE_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// electric_current_d
+
+template<>
+struct unit_info< electric_current_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "ampere"; }
+   static std::string symbol() { return "A"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_AMPERE_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_becquerel.hpp b/third_party/phys/units/quantity_io_becquerel.hpp
new file mode 100644
index 00000000..deaf47c3
--- /dev/null
+++ b/third_party/phys/units/quantity_io_becquerel.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_becquerel.hpp
+ *
+ * \brief   becquerel, activity_of_a_nuclide_d
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_BECQUEREL_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_BECQUEREL_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * becquerel, [Bq].
+ */
+template<>
+struct unit_info< activity_of_a_nuclide_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "becquerel"; }
+    static std::string symbol() { return "Bq"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Bq, activity_of_a_nuclide_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_BECQUEREL_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_candela.hpp b/third_party/phys/units/quantity_io_candela.hpp
new file mode 100644
index 00000000..8814dbb2
--- /dev/null
+++ b/third_party/phys/units/quantity_io_candela.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_candela.hpp
+ *
+ * \brief   candela, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_CANDELA_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_CANDELA_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// luminous_intensity_d
+
+template<>
+struct unit_info< luminous_intensity_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "candela"; }
+   static std::string symbol() { return "cd"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_CANDELA_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_celsius.hpp b/third_party/phys/units/quantity_io_celsius.hpp
new file mode 100644
index 00000000..fc769a4d
--- /dev/null
+++ b/third_party/phys/units/quantity_io_celsius.hpp
@@ -0,0 +1,46 @@
+/**
+ * \file quantity_io_celsius.hpp
+ *
+ * \brief   celsius, thermodynamic temperature.
+ * \author  Martin Moene
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_CELSIUS_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_CELSIUS_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * celsius, [°C].
+ */
+template<>
+struct unit_info< thermodynamic_temperature_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "celsius"; }
+    static std::string symbol() { return "°C"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( oC, thermodynamic_temperature_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_CELSIUS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_coulomb.hpp b/third_party/phys/units/quantity_io_coulomb.hpp
new file mode 100644
index 00000000..0f140d78
--- /dev/null
+++ b/third_party/phys/units/quantity_io_coulomb.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_coulomb.hpp
+ *
+ * \brief   coulomb, electrical power.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_COULOMB_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_COULOMB_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * coulomb, [C].
+ */
+template<>
+struct unit_info< electric_charge_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "coulomb"; }
+    static std::string symbol() { return "C"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( C, electric_charge_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_COULOMB_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_dimensionless.hpp b/third_party/phys/units/quantity_io_dimensionless.hpp
new file mode 100644
index 00000000..1d1ca57e
--- /dev/null
+++ b/third_party/phys/units/quantity_io_dimensionless.hpp
@@ -0,0 +1,40 @@
+/**
+ * \file quantity_io_dimensionless.hpp
+ *
+ * \brief   dimensionless.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_DIMENSIONLESS_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_DIMENSIONLESS_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * (dimensionless), [].
+ */
+template<>
+struct unit_info< dimensionless_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "(dimensionless)"; }
+    static std::string symbol() { return "[]"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_DIMENSIONLESS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_engineering.hpp b/third_party/phys/units/quantity_io_engineering.hpp
new file mode 100644
index 00000000..0423f5ac
--- /dev/null
+++ b/third_party/phys/units/quantity_io_engineering.hpp
@@ -0,0 +1,173 @@
+/**
+ * \file io_output_engineering.hpp
+ *
+ * \brief   Engineering IO for quantity library.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ *
+ * Based on the following question and answer on StackOverflow:
+ * Convert float number to string with engineering notation (with SI prefixe) in Python [closed].
+ * Asked by working4coins, http://stackoverflow.com/users/2051311/working4coins
+ * Answered by scls, http://stackoverflow.com/users/1609077/scls
+ * http://stackoverflow.com/questions/15733772/convert-float-number-to-string-with-engineering-notation-with-si-prefixe-in-py
+ *
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+#include <cmath>
+#include <iomanip>
+#include <limits>
+#include <sstream>
+
+/*
+ * Note: micro, µ, may not work everywhere, so you can define a glyph yourself:
+ */
+#ifndef ENG_FORMAT_MICRO_GLYPH
+# define ENG_FORMAT_MICRO_GLYPH "u"
+#endif
+
+/// namespace phys.
+
+namespace phys {
+
+/// namespace units.
+
+namespace units {
+
+/// namespace detail.
+
+namespace detail {
+
+char const * const prefixes[/*exp*/][2][9] =
+{
+    {
+        {   "",   "m",   ENG_FORMAT_MICRO_GLYPH
+                            ,   "n",    "p",    "f",    "a",    "z",    "y", },
+        {   "",   "k",   "M",   "G",    "T",    "P",    "E",    "Z",    "Y", },
+    },
+    {
+        { "e0", "e-3", "e-6", "e-9", "e-12", "e-15", "e-18", "e-21", "e-24", },
+        { "e0",  "e3",  "e6",  "e9",  "e12",  "e15",  "e18",  "e21",  "e24", },
+    },
+};
+
+template<typename T, size_t N>
+constexpr size_t dimenson_of( T(&)[N] )
+{
+    return N;
+}
+
+constexpr int prefix_count = dimenson_of( prefixes[false][false]  );
+
+inline int sign( int const value )
+{
+    return value == 0 ? +1 : value / std::abs( value );
+}
+
+inline bool iszero( double const value )
+{
+    return FP_ZERO == std::fpclassify( value );
+}
+
+inline long degree_of( double const value )
+{
+    return iszero( value ) ? 0 : std::lrint( std::floor( std::log10( std::abs( value ) ) / 3) );
+}
+
+inline int precision( double const scaled, int const digits )
+{
+    return iszero( scaled ) ? digits - 1 : digits - std::log10( std::abs( scaled ) ) - 2 * std::numeric_limits<double>::epsilon();
+}
+
+inline std::string prefix_or_exponent( bool const exponential, int const degree )
+{
+    return std::string( exponential || 0 == degree ? "" : " " ) + prefixes[ exponential ][ sign(degree) > 0 ][ std::abs( degree ) ];
+}
+
+inline std::string exponent( int const degree )
+{
+    std::ostringstream os;
+    os << "e" << 3 * degree;
+    return os.str();
+}
+
+inline std::string bracket( std::string const unit )
+{
+	return std::string::npos != unit.find_first_of( "+- " ) ? "(" + unit + ")" : unit;
+}
+
+} // anonymous namespace
+
+/**
+ * convert real number to prefixed or exponential notation, optionally followed by a unit.
+ */
+inline std::string
+to_engineering_string( double const value, int const digits = 3, bool exponential = false, bool const showpos = false, std::string const unit = "" )
+{
+    using namespace detail;
+
+    if      ( std::isnan( value ) ) return "NaN";
+    else if ( std::isinf( value ) ) return "INFINITE";
+
+    const int degree = degree_of( value );
+
+    std::string factor;
+
+    if ( std::abs( degree ) < prefix_count )
+    {
+        factor = prefix_or_exponent( exponential, degree );
+    }
+    else
+    {
+        exponential = true;
+        factor = exponent( degree );
+    }
+
+    std::ostringstream os;
+
+    const double scaled = value * std::pow( 1000.0, -degree );
+
+    const std::string space = ( 0 == degree || exponential ) && unit.length() ? " ":"";
+
+    os << std::fixed << (showpos ? std::showpos : std::noshowpos) << std::setprecision( precision(scaled, digits) ) << scaled << factor << space << bracket( unit );
+
+    return os.str();
+}
+
+namespace io {
+namespace eng {
+
+template< typename Dims, typename T >
+std::string to_string( quantity<Dims, T> const & q, int const digits = 3, bool const exponential = false, bool const showpos = false )
+{
+   return to_engineering_string( q.magnitude(), digits, exponential, showpos, to_unit_symbol( q ) );
+}
+
+template< typename Dims, typename T >
+inline std::ostream & operator<<( std::ostream & os, quantity< Dims, T > const & q )
+{
+   return os << to_string( q );
+}
+
+} // namespace eng
+} // namespace io
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED
+
+/*
+ * end of file
+ */
+
diff --git a/third_party/phys/units/quantity_io_farad.hpp b/third_party/phys/units/quantity_io_farad.hpp
new file mode 100644
index 00000000..fcd0c445
--- /dev/null
+++ b/third_party/phys/units/quantity_io_farad.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_farad.hpp
+ *
+ * \brief   farad, capacitance.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_FARAD_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_FARAD_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * farad, [F].
+ */
+template<>
+struct unit_info< capacitance_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "farad"; }
+    static std::string symbol() { return "F"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( F, capacitance_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_FARAD_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_gray.hpp b/third_party/phys/units/quantity_io_gray.hpp
new file mode 100644
index 00000000..769110dd
--- /dev/null
+++ b/third_party/phys/units/quantity_io_gray.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_gray.hpp
+ *
+ * \brief   gray, absorbed dose.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_GRAY_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_GRAY_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * gray, [Gy].
+ */
+template<>
+struct unit_info< absorbed_dose_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "gray"; }
+    static std::string symbol() { return "Gy"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Gy, absorbed_dose_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_GRAY_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_henry.hpp b/third_party/phys/units/quantity_io_henry.hpp
new file mode 100644
index 00000000..d1e73363
--- /dev/null
+++ b/third_party/phys/units/quantity_io_henry.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_henry.hpp
+ *
+ * \brief   henry, inductance.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_HENRY_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_HENRY_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * henry, [H].
+ */
+template<>
+struct unit_info< inductance_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "henry"; }
+    static std::string symbol() { return "H"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( H, inductance_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_HENRY_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_hertz.hpp b/third_party/phys/units/quantity_io_hertz.hpp
new file mode 100644
index 00000000..3695e543
--- /dev/null
+++ b/third_party/phys/units/quantity_io_hertz.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_hertz.hpp
+ *
+ * \brief   hertz, frequency.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_HERTZ_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_HERTZ_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * hertz, [Hz].
+ */
+template<>
+struct unit_info< frequency_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "hertz"; }
+   static std::string symbol() { return "Hz"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Hz, frequency_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_HERTZ_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_joule.hpp b/third_party/phys/units/quantity_io_joule.hpp
new file mode 100644
index 00000000..33f26c58
--- /dev/null
+++ b/third_party/phys/units/quantity_io_joule.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_joule.hpp
+ *
+ * \brief   joule, energy.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_JOULE_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_JOULE_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * joule, [J].
+ */
+template<>
+struct unit_info< energy_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "joule"; }
+    static std::string symbol() { return "J"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( J, energy_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_JOULE_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_kelvin.hpp b/third_party/phys/units/quantity_io_kelvin.hpp
new file mode 100644
index 00000000..24dfa48b
--- /dev/null
+++ b/third_party/phys/units/quantity_io_kelvin.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_kelvin.hpp
+ *
+ * \brief   kelvin, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_KELVIN_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_KELVIN_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// kelvin, [K].
+
+template<>
+struct unit_info< thermodynamic_temperature_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "kelvin"; }
+    static std::string symbol() { return "K"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_KELVIN_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_kilogram.hpp b/third_party/phys/units/quantity_io_kilogram.hpp
new file mode 100644
index 00000000..375cdc51
--- /dev/null
+++ b/third_party/phys/units/quantity_io_kilogram.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_kilogram.hpp
+ *
+ * \brief   kilogram, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_KILOGRAM_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_KILOGRAM_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// mass_d
+
+template<>
+struct unit_info< mass_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "kilogram"; }
+   static std::string symbol() { return "kg"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_KILOGRAM_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_lumen.hpp b/third_party/phys/units/quantity_io_lumen.hpp
new file mode 100644
index 00000000..f5443b50
--- /dev/null
+++ b/third_party/phys/units/quantity_io_lumen.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_lumen.hpp
+ *
+ * \brief   lumen, luminous flux.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_LUMEN_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_LUMEN_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * lumen, [lm].
+ */
+template<>
+struct unit_info< luminous_flux_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "lumen"; }
+    static std::string symbol() { return "lm"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( lm, luminous_flux_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_LUMEN_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_lux.hpp b/third_party/phys/units/quantity_io_lux.hpp
new file mode 100644
index 00000000..98a8d9e4
--- /dev/null
+++ b/third_party/phys/units/quantity_io_lux.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_lux.hpp
+ *
+ * \brief   lux, illuminance.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_LUX_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_LUX_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * lux, [lx].
+ */
+template<>
+struct unit_info< illuminance_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "lux"; }
+    static std::string symbol() { return "lx"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( lx, illuminance_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_LUX_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_meter.hpp b/third_party/phys/units/quantity_io_meter.hpp
new file mode 100644
index 00000000..4b537d50
--- /dev/null
+++ b/third_party/phys/units/quantity_io_meter.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_meter.hpp
+ *
+ * \brief   meter, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_METER_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_METER_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// meter_d
+
+template<>
+struct unit_info< length_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "meter"; }
+   static std::string symbol() { return "m"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_METER_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_mole.hpp b/third_party/phys/units/quantity_io_mole.hpp
new file mode 100644
index 00000000..cd3b184d
--- /dev/null
+++ b/third_party/phys/units/quantity_io_mole.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_meter.hpp
+ *
+ * \brief   meter, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_MOLE_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_MOLE_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// amount_of_substance_d
+
+template<>
+struct unit_info< amount_of_substance_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "mole"; }
+   static std::string symbol() { return "mol"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_MOLE_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_newton.hpp b/third_party/phys/units/quantity_io_newton.hpp
new file mode 100644
index 00000000..4a7505e6
--- /dev/null
+++ b/third_party/phys/units/quantity_io_newton.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_newton.hpp
+ *
+ * \brief   newton, force.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_NEWTON_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_NEWTON_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * newton, [N].
+ */
+template<>
+struct unit_info< force_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "newton"; }
+    static std::string symbol() { return "N"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( N, force_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_NEWTON_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_ohm.hpp b/third_party/phys/units/quantity_io_ohm.hpp
new file mode 100644
index 00000000..84d33c7e
--- /dev/null
+++ b/third_party/phys/units/quantity_io_ohm.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_ohm.hpp
+ *
+ * \brief   Ohm, electrical resistance.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_OHM_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_OHM_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * ohm, [Ohm].
+ */
+template<>
+struct unit_info< electric_resistance_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "ohm"; }
+    static std::string symbol() { return "Ohm"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Ohm, electric_resistance_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_OHM_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_pascal.hpp b/third_party/phys/units/quantity_io_pascal.hpp
new file mode 100644
index 00000000..011e3da4
--- /dev/null
+++ b/third_party/phys/units/quantity_io_pascal.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_pascal.hpp
+ *
+ * \brief   pascal, pressure.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_PASCAL_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_PASCAL_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * pascal, [Pa].
+ */
+template<>
+struct unit_info< pressure_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "pascal"; }
+    static std::string symbol() { return "Pa"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Pa, pressure_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_PASCAL_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_radian.hpp b/third_party/phys/units/quantity_io_radian.hpp
new file mode 100644
index 00000000..780e1bce
--- /dev/null
+++ b/third_party/phys/units/quantity_io_radian.hpp
@@ -0,0 +1,44 @@
+/**
+ * \file quantity_io_radian.hpp
+ *
+ * \brief   radian, angle
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_RADIAN_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_RADIAN_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+#if 0
+template<>
+struct unit_info< radian_d >
+{
+    static std::string name()   { return "radian"; }
+    static std::string symbol() { return "rad"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( rad, radian_d )
+
+}
+#endif
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_RADIAN_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_second.hpp b/third_party/phys/units/quantity_io_second.hpp
new file mode 100644
index 00000000..31edd4de
--- /dev/null
+++ b/third_party/phys/units/quantity_io_second.hpp
@@ -0,0 +1,39 @@
+/**
+ * \file quantity_io_second.hpp
+ *
+ * \brief   second, fundamental dimension.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_SECOND_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_SECOND_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/// time_interval_d
+
+template<>
+struct unit_info< time_interval_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "second"; }
+   static std::string symbol() { return "s"; }
+};
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_SECOND_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_siemens.hpp b/third_party/phys/units/quantity_io_siemens.hpp
new file mode 100644
index 00000000..34f145de
--- /dev/null
+++ b/third_party/phys/units/quantity_io_siemens.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_siemens.hpp
+ *
+ * \brief   siemens, electrical coductance.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_SIEMENS_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_SIEMENS_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * siemens, [S].
+ */
+template<>
+struct unit_info< electric_conductance_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "siemens"; }
+    static std::string symbol() { return "S"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( S, electric_conductance_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_SIEMENS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_sievert.hpp b/third_party/phys/units/quantity_io_sievert.hpp
new file mode 100644
index 00000000..971ca155
--- /dev/null
+++ b/third_party/phys/units/quantity_io_sievert.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_sievert.hpp
+ *
+ * \brief   sievert, dose equivalent.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_SIEVERT_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_SIEVERT_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * sievert, [Sv].
+ */
+template<>
+struct unit_info< dose_equivalent_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "sievert"; }
+    static std::string symbol() { return "Sv"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Sv, dose_equivalent_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_SIEVERT_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_speed.hpp b/third_party/phys/units/quantity_io_speed.hpp
new file mode 100644
index 00000000..7a6f6318
--- /dev/null
+++ b/third_party/phys/units/quantity_io_speed.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_speed.hpp
+ *
+ * \brief   speed, velocity.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_SPEED_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_SPEED_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * meter per second, [m/s].
+ */
+template<>
+struct unit_info< speed_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "Meter per second"; }
+    static std::string symbol() { return "m/s"; }
+};
+
+namespace literals {
+
+//QUANTITY_DEFINE_LITERALS( m/s, speed_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_SPEED_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_steradian.hpp b/third_party/phys/units/quantity_io_steradian.hpp
new file mode 100644
index 00000000..87a977e5
--- /dev/null
+++ b/third_party/phys/units/quantity_io_steradian.hpp
@@ -0,0 +1,44 @@
+/**
+ * \file quantity_io_steradian.hpp
+ *
+ * \brief   steradian, solid angle
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_STERADIAN_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_STERADIAN_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+#if 0
+template<>
+struct unit_info< steradian_d >
+{
+    static std::string name()   { return "steradian"; }
+    static std::string symbol() { return "sr"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( sr, steradian_d )
+
+}
+#endif
+
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_STERADIAN_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_symbols.hpp b/third_party/phys/units/quantity_io_symbols.hpp
new file mode 100644
index 00000000..41dc6189
--- /dev/null
+++ b/third_party/phys/units/quantity_io_symbols.hpp
@@ -0,0 +1,57 @@
+/**
+ * \file quantity_io_symbols.hpp
+ *
+ * \brief   load all available unit names and symbols.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_SYMBOLS_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_SYMBOLS_HPP_INCLUDED
+
+#include "phys/units/quantity_io_ampere.hpp"
+//prefer Hertz
+//#include "phys/units/quantity_io_becquerel.hpp"
+#include "phys/units/quantity_io_candela.hpp"
+//prefer kelvin
+//#include "phys/units/quantity_io_celsius.hpp"
+#include "phys/units/quantity_io_coulomb.hpp"
+#include "phys/units/quantity_io_dimensionless.hpp"
+#include "phys/units/quantity_io_farad.hpp"
+//prefer sievert
+//#include "phys/units/quantity_io_gray.hpp"
+#include "phys/units/quantity_io_joule.hpp"
+#include "phys/units/quantity_io_henry.hpp"
+#include "phys/units/quantity_io_hertz.hpp"
+#include "phys/units/quantity_io_kelvin.hpp"
+#include "phys/units/quantity_io_kilogram.hpp"
+//prefer Cd base unit
+//#include "phys/units/quantity_io_lumen.hpp"
+#include "phys/units/quantity_io_lux.hpp"
+#include "phys/units/quantity_io_meter.hpp"
+#include "phys/units/quantity_io_newton.hpp"
+#include "phys/units/quantity_io_ohm.hpp"
+#include "phys/units/quantity_io_pascal.hpp"
+#include "phys/units/quantity_io_radian.hpp"
+#include "phys/units/quantity_io_second.hpp"
+#include "phys/units/quantity_io_siemens.hpp"
+#include "phys/units/quantity_io_sievert.hpp"
+#include "phys/units/quantity_io_speed.hpp"
+#include "phys/units/quantity_io_steradian.hpp"
+#include "phys/units/quantity_io_tesla.hpp"
+#include "phys/units/quantity_io_volt.hpp"
+#include "phys/units/quantity_io_watt.hpp"
+#include "phys/units/quantity_io_weber.hpp"
+
+#endif // PHYS_UNITS_QUANTITY_IO_SYMBOLS_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_tesla.hpp b/third_party/phys/units/quantity_io_tesla.hpp
new file mode 100644
index 00000000..fc4e651c
--- /dev/null
+++ b/third_party/phys/units/quantity_io_tesla.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_tesla.hpp
+ *
+ * \brief   tesla, magnetic flux density.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_TESLA_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_TESLA_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * tesla, [T].
+ */
+template<>
+struct unit_info< magnetic_flux_density_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "tesla"; }
+    static std::string symbol() { return "T"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( T, magnetic_flux_density_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_TESLA_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_volt.hpp b/third_party/phys/units/quantity_io_volt.hpp
new file mode 100644
index 00000000..baacf390
--- /dev/null
+++ b/third_party/phys/units/quantity_io_volt.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_volt.hpp
+ *
+ * \brief   voltage, electric potential.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_VOLT_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_VOLT_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * volt, [V].
+ */
+template<>
+struct unit_info< electric_potential_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "volt"; }
+    static std::string symbol() { return "V"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( V, electric_potential_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_VOLT_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_watt.hpp b/third_party/phys/units/quantity_io_watt.hpp
new file mode 100644
index 00000000..7e616c70
--- /dev/null
+++ b/third_party/phys/units/quantity_io_watt.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_watt.hpp
+ *
+ * \brief   watt, electrical power.
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_WATT_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_WATT_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * watt, [W].
+ */
+template<>
+struct unit_info< power_d >
+{
+   static bool        single() { return true; }
+   static std::string name()   { return "watt"; }
+   static std::string symbol() { return "W"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( W, power_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_WATT_HPP_INCLUDED
+
+/*
+ * end of file
+ */
diff --git a/third_party/phys/units/quantity_io_weber.hpp b/third_party/phys/units/quantity_io_weber.hpp
new file mode 100644
index 00000000..95ab6167
--- /dev/null
+++ b/third_party/phys/units/quantity_io_weber.hpp
@@ -0,0 +1,45 @@
+/**
+ * \file quantity_io_weber.hpp
+ *
+ * \brief   weber, magnetic flux
+ * \author  Martin Moene
+ * \date    7 September 2013
+ * \since   1.0
+ *
+ * Copyright 2013 Universiteit Leiden. All rights reserved.
+ * This code is provided as-is, with no warrantee of correctness.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PHYS_UNITS_QUANTITY_IO_WEBER_HPP_INCLUDED
+#define PHYS_UNITS_QUANTITY_IO_WEBER_HPP_INCLUDED
+
+#include "phys/units/quantity_io.hpp"
+
+namespace phys { namespace units {
+
+/**
+ * weber, [Wb].
+ */
+template<>
+struct unit_info< magnetic_flux_d >
+{
+    static bool        single() { return true; }
+    static std::string name()   { return "weber"; }
+    static std::string symbol() { return "Wb"; }
+};
+
+namespace literals {
+
+QUANTITY_DEFINE_LITERALS( Wb, magnetic_flux_d )
+
+}
+}} // namespace phys::units
+
+#endif // PHYS_UNITS_QUANTITY_IO_WEBER_HPP_INCLUDED
+
+/*
+ * end of file
+ */
-- 
GitLab