Units of data

View: New views
13 Messages — Rating Filter:   Alert me  

Units of data

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Has anyone extended (even privately) Boost.Units to include support
for units of data (bits, bytes, KB, MB, etc)?  It seems like this
would be a useful addition to Boost.Units.

Assuming no, what is the minimum amount of work required to do this
myself?  There's not a lot of info in the docs on how to define new
base units, although I've already begun looking over the source code
to try to come up with something.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Zachary Turner wrote:
> Has anyone extended (even privately) Boost.Units to include support
> for units of data (bits, bytes, KB, MB, etc)?  It seems like this
> would be a useful addition to Boost.Units.
>
> Assuming no, what is the minimum amount of work required to do this
> myself?  There's not a lot of info in the docs on how to define new
> base units, although I've already begun looking over the source code
> to try to come up with something

warning untested code.

#include <boost/units/base_dimension.hpp>
#include <boost/units/base_unit.hpp>
#include <boost/units/scale.hpp>
#include <boost/units/scaled_base_unit.hpp>

// note that the numbers here are arbitrary as long as they are unique.
struct data_base_dimension :
boost::units::base_dimension<data_base_dimension, 73254> {};
typedef data_base_dimension::dimension_type data_dimension;

struct bit_base_unit : boost::units::base_unit<bit_base_unit,
data_dimension, 76389> {};
typedef boost::units::scaled_base_unit<bit_base_unit,
boost::units::scale<8> > byte_base_unit;

namespace boost {
namespace units {
template<>
struct base_unit_info< ::byte_base_unit> {
    static const char* name() { return("byte"); }
    static const char* symbol() { return("B"); }
};
}
}

typedef boost::units::scaled_base_unit<byte_base_unit,
boost::units::scale<2, boost::units::static_rational<10> > > KB_base_unit;
typedef boost::units::scaled_base_unit<byte_base_unit,
boost::units::scale<2, boost::units::static_rational<20> > > MB_base_unit;
typedef boost::units::scaled_base_unit<byte_base_unit,
boost::units::scale<2, boost::units::static_rational<30> > > GB_base_unit;
typedef boost::units::scaled_base_unit<byte_base_unit,
boost::units::scale<2, boost::units::static_rational<40> > > TB_base_unit;

See also
http://www.boost.org/doc/html/boost_units/Dimensional_Analysis.html
http://www.boost.org/doc/html/boost_units/Units.html
I believe that these two pages show creating a minimal SI system from
scratch.

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Jul 1, 2009 at 7:41 PM, Steven Watanabe<watanabesj@...> wrote:

> AMDG
>
> Zachary Turner wrote:
>>
>> Has anyone extended (even privately) Boost.Units to include support
>> for units of data (bits, bytes, KB, MB, etc)?  It seems like this
>> would be a useful addition to Boost.Units.
>>
>> Assuming no, what is the minimum amount of work required to do this
>> myself?  There's not a lot of info in the docs on how to define new
>> base units, although I've already begun looking over the source code
>> to try to come up with something
>
> warning untested code.
>
> #include <boost/units/base_dimension.hpp>
> #include <boost/units/base_unit.hpp>
> #include <boost/units/scale.hpp>
> #include <boost/units/scaled_base_unit.hpp>
>
> // note that the numbers here are arbitrary as long as they are unique.
> struct data_base_dimension :
> boost::units::base_dimension<data_base_dimension, 73254> {};
> typedef data_base_dimension::dimension_type data_dimension;
>
> struct bit_base_unit : boost::units::base_unit<bit_base_unit,
> data_dimension, 76389> {};
> typedef boost::units::scaled_base_unit<bit_base_unit, boost::units::scale<8>
>> byte_base_unit;
>
> namespace boost {
> namespace units {
> template<>
> struct base_unit_info< ::byte_base_unit> {
>   static const char* name() { return("byte"); }
>   static const char* symbol() { return("B"); }
> };
> }
> }
>
> typedef boost::units::scaled_base_unit<byte_base_unit,
> boost::units::scale<2, boost::units::static_rational<10> > > KB_base_unit;
> typedef boost::units::scaled_base_unit<byte_base_unit,
> boost::units::scale<2, boost::units::static_rational<20> > > MB_base_unit;
> typedef boost::units::scaled_base_unit<byte_base_unit,
> boost::units::scale<2, boost::units::static_rational<30> > > GB_base_unit;
> typedef boost::units::scaled_base_unit<byte_base_unit,
> boost::units::scale<2, boost::units::static_rational<40> > > TB_base_unit;
>
> See also
> http://www.boost.org/doc/html/boost_units/Dimensional_Analysis.html
> http://www.boost.org/doc/html/boost_units/Units.html
> I believe that these two pages show creating a minimal SI system from
> scratch.
>

Thanks for your response.  I got this working mostly, but I'm still
having difficulty seeing how to tie it all together.  I added the
following:

typedef boost::units::make_system<bit_base_unit>::type data_system;
typedef boost::units::unit<data_base_dimension::dimension_type,
data_system> capacity;

But I'm still not sure how to create and manipulate values with these
units.  For example, I can do:

quantity<capacity> compressed_size;

but if I try to assign it to anything I get errors.  I tried using the
BOOST_UNITS_STATIC_CONSTANT macro to create aliases such as bytes,
megabytes, etc but I think this is the wrong approach, is it because
all the units above are defined as base units?

Ideally I want to be able to type:

quantity<capacity> compressed_size = 10000 * bytes;
quantity<capacity> total_size = 400000 * bytes;

float ratio = compressed_size / total_size;  //should be dimensionless

quantity<time> duration = 300 * seconds;

quantity<data_rate> = total_size / duration;  //has dimensions capacity/time
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Zachary Turner wrote:

> Thanks for your response.  I got this working mostly, but I'm still
> having difficulty seeing how to tie it all together.  I added the
> following:
>
> typedef boost::units::make_system<bit_base_unit>::type data_system;
> typedef boost::units::unit<data_base_dimension::dimension_type,
> data_system> capacity;
>
> But I'm still not sure how to create and manipulate values with these
> units.  For example, I can do:
>
> quantity<capacity> compressed_size;
>
> but if I try to assign it to anything I get errors.  I tried using the
> BOOST_UNITS_STATIC_CONSTANT macro to create aliases such as bytes,
> megabytes, etc but I think this is the wrong approach, is it because
> all the units above are defined as base units?
>
> Ideally I want to be able to type:
>
> quantity<capacity> compressed_size = 10000 * bytes;
>  

That won't quite work.  Implicit conversions are banned.

typedef byte_base_unit::unit_type bytes;

quantity<capacity> compressed_size(10000 * bytes());

You can also use
BOOST_UNITS_STATIC_CONSTANT(bytes, byte_base_unit::unit_type);

to allow
10000 * bytes;

> quantity<capacity> total_size = 400000 * bytes;
>
> float ratio = compressed_size / total_size;  //should be dimensionless
>  

This ought to work.

> quantity<time> duration = 300 * seconds;
>
> quantity<data_rate> = total_size / duration;  //has dimensions capacity/tim

This should work if data_rate is defined correctly.

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Jul 1, 2009 at 11:26 PM, Steven Watanabe<watanabesj@...> wrote:

> AMDG
>
> Zachary Turner wrote:
>>
>> Thanks for your response.  I got this working mostly, but I'm still
>> having difficulty seeing how to tie it all together.  I added the
>> following:
>>
>> typedef boost::units::make_system<bit_base_unit>::type data_system;
>> typedef boost::units::unit<data_base_dimension::dimension_type,
>> data_system>    capacity;
>>
>> But I'm still not sure how to create and manipulate values with these
>> units.  For example, I can do:
>>
>> quantity<capacity> compressed_size;
>>
>> but if I try to assign it to anything I get errors.  I tried using the
>> BOOST_UNITS_STATIC_CONSTANT macro to create aliases such as bytes,
>> megabytes, etc but I think this is the wrong approach, is it because
>> all the units above are defined as base units?
>>
>> Ideally I want to be able to type:
>>
>> quantity<capacity> compressed_size = 10000 * bytes;
>>
>
> That won't quite work.  Implicit conversions are banned.
>
> typedef byte_base_unit::unit_type bytes;
>
> quantity<capacity> compressed_size(10000 * bytes());
>
> You can also use
> BOOST_UNITS_STATIC_CONSTANT(bytes, byte_base_unit::unit_type);
>
> to allow
> 10000 * bytes;
>
>> quantity<capacity> total_size = 400000 * bytes;
>>
>> float ratio = compressed_size / total_size;  //should be dimensionless
>>
>
> This ought to work.


Thanks for your help so far!  I know I'm probably just making this too
difficult, but it's still not working.  I guess I should just post a
complete sample so that we can eliminate the snip factor from the list
of possible causes  (I put them in the boost namespace for the sake of
consistency but the same problem arises regardless).

//units.hpp

#ifndef UNITS_HPP_INCLUDED
#define UNITS_HPP_INCLUDED

#include <boost/units/base_dimension.hpp>
#include <boost/units/base_unit.hpp>
#include <boost/units/scale.hpp>
#include <boost/units/scaled_base_unit.hpp>
#include <boost/units/make_system.hpp>
#include <boost/units/static_constant.hpp>

#define DECLARE_BASE_UNIT_INFO(base_unit_, name_, symbol_) \
template<> struct base_unit_info<base_unit_> { \
        static const char* name() { return name_; } \
        static const char* symbol() { return symbol_; } \
};

namespace boost {

namespace units {

namespace data_capacity
{

struct data_capacity_base_dimension :
base_dimension<data_capacity_base_dimension, 73254> {};
typedef data_capacity_base_dimension::dimension_type data_capacity_dimension;

struct bit_base_unit : base_unit<bit_base_unit,
data_capacity_dimension, 76389> {};

typedef scaled_base_unit<bit_base_unit, scale<2, static_rational<3> >
> byte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<10>
> > kilobyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<20>
> > megabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<30>
> > gigabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<40>
> > terabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<50>
> > petabyte_base_unit;

}

DECLARE_BASE_UNIT_INFO(data_capacity::bit_base_unit, "bit", "b")
DECLARE_BASE_UNIT_INFO(data_capacity::byte_base_unit, "byte", "B")
DECLARE_BASE_UNIT_INFO(data_capacity::kilobyte_base_unit, "kilobyte", "KB")
DECLARE_BASE_UNIT_INFO(data_capacity::megabyte_base_unit, "megabyte", "MB")
DECLARE_BASE_UNIT_INFO(data_capacity::gigabyte_base_unit, "gigabyte", "GB")
DECLARE_BASE_UNIT_INFO(data_capacity::terabyte_base_unit, "terabyte", "TB")
DECLARE_BASE_UNIT_INFO(data_capacity::petabyte_base_unit, "petabyte", "PB")

namespace data_capacity {

typedef boost::units::make_system<bit_base_unit>::type data_capacity_system;
typedef boost::units::unit<data_capacity_base_dimension::dimension_type,
data_capacity_system> data_capacity;

BOOST_UNITS_STATIC_CONSTANT(bit, bit_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(bits, bit_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(byte, byte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(bytes, byte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(kilobyte, kilobyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(kilobytes, kilobyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(megabyte, megabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(megabytes, megabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(gigabyte, gigabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(gigabytes, gigabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(terabyte, terabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(terabytes, terabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(petabyte, petabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(petabytes, petabyte_base_unit::unit_type);

}
}
}

#endif


//test.cpp

#include "units.hpp"
#include <boost/units/quantity.hpp>

void foo()
{
        using boost::units::quantity;
        using namespace boost::units::data_capacity;

        //Both of these fail with the message that there is no
conversion to the destination
        //type because the construcor is explicit
        quantity<data_capacity> compressed_size = 1000 * bytes;
        quantity<data_capacity, int> compressed_size2 = 1000 * bytes;

        //Succeeds but gives a horribly long warning about conversion from
'double' to 'const int'
        //at file 'boost/units/detail/conversion_impl.hpp(342)', reference to
class template instantiation at
        //boost/units/quantity.hpp(182)
        quantity<data_capacity, int> compressed_size3(1000 * bytes);
}



>
>> quantity<time> duration = 300 * seconds;
>>
>> quantity<data_rate> = total_size / duration;  //has dimensions
>> capacity/tim
>
> This should work if data_rate is defined correctly.
>
Hopefully once I get this working I'll be able to figure that one out on my own!

Thanks
Zach
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Zachary Turner wrote:

> Thanks for your help so far!  I know I'm probably just making this too
> difficult, but it's still not working.  I guess I should just post a
> complete sample so that we can eliminate the snip factor from the list
> of possible causes  (I put them in the boost namespace for the sake of
> consistency but the same problem arises regardless).
>
> <snip>
>  
> void foo()
> {
> using boost::units::quantity;
> using namespace boost::units::data_capacity;
>
>         //Both of these fail with the message that there is no
> conversion to the destination
>         //type because the construcor is explicit
> quantity<data_capacity> compressed_size = 1000 * bytes;
> quantity<data_capacity, int> compressed_size2 = 1000 * bytes;
>  

Implicit conversion between different units is not allowed.
Try
quantity<data_capacity> compressed_size(1000 * bytes);

> //Succeeds but gives a horribly long warning about conversion from
> 'double' to 'const int'
> //at file 'boost/units/detail/conversion_impl.hpp(342)', reference to
> class template instantiation at
> //boost/units/quantity.hpp(182)
>         quantity<data_capacity, int> compressed_size3(1000 * bytes);
> }
>  

I'll commit a fix as soon as the regression tests finish locally.

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Matthias Schabel-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> void foo()
> {
> using boost::units::quantity;
> using namespace boost::units::data_capacity;
>
>        //Both of these fail with the message that there is no
> conversion to the destination
>        //type because the construcor is explicit
> quantity<data_capacity> compressed_size = 1000 * bytes;
> quantity<data_capacity, int> compressed_size2 = 1000 * bytes;

Implicit conversion is not allowed, and default value type is double -  
try :

quantity<data_capacity>      compressed_size(1000.0*bytes);
quantity<data_capacity,int> compressed_size2(1000*bytes);


> //Succeeds but gives a horribly long warning about conversion from
> 'double' to 'const int'
> //at file 'boost/units/detail/conversion_impl.hpp(342)', reference to
> class template instantiation at
> //boost/units/quantity.hpp(182)
>       quantity<data_capacity, int> compressed_size3(1000 * bytes);
> }

If I remember correctly, this stems from the use of double precision  
in the conversion code. I think it would be difficult to get rid of  
this - most computations involving unit conversions do not involve  
exact integer arithmetic...

Matthias
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Matthias Schabel wrote:

>>     //Succeeds but gives a horribly long warning about conversion from
>> 'double' to 'const int'
>>     //at file 'boost/units/detail/conversion_impl.hpp(342)',
>> reference to
>> class template instantiation at
>>     //boost/units/quantity.hpp(182)
>>           quantity<data_capacity, int> compressed_size3(1000 * bytes);
>> }
>
> If I remember correctly, this stems from the use of double precision
> in the conversion code. I think it would be difficult to get rid of
> this - most computations involving unit conversions do not involve
> exact integer arithmetic...

Getting rid of the warning shouldn't be a problem.
I'm just going to add a cast.  This ought to be safe,
since the conversion is explicit.  A cast is only
needed at the end, because all the conversion code
is careful to deduce the correct return type for all
operators.

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Jul 2, 2009 at 2:07 PM, Steven Watanabe<watanabesj@...> wrote:

> AMDG
>
> Zachary Turner wrote:
>>
>> Thanks for your help so far!  I know I'm probably just making this too
>> difficult, but it's still not working.  I guess I should just post a
>> complete sample so that we can eliminate the snip factor from the list
>> of possible causes  (I put them in the boost namespace for the sake of
>> consistency but the same problem arises regardless).
>>
>> <snip>
>>  void foo()
>> {
>>        using boost::units::quantity;
>>        using namespace boost::units::data_capacity;
>>
>>        //Both of these fail with the message that there is no
>> conversion to the destination
>>        //type because the construcor is explicit
>>        quantity<data_capacity> compressed_size = 1000 * bytes;
>>        quantity<data_capacity, int> compressed_size2 = 1000 * bytes;
>>
>
> Implicit conversion between different units is not allowed.
> Try
> quantity<data_capacity> compressed_size(1000 * bytes);

Thanks.  The confusion came from the fact that the syntax I was trying
was being used in some of the examples.  But there is something
different about those examples, so that's why it wasn't working.  One
of the trig examples has a line:

quantity<plane_angle>           theta = 0.375*radians;

for example.   I suppose it's due to the fact that radians are the
"primary" unit for this dimension?

That aside, I still think something isn't exactly right.  Ultimately I
need to be able to print these quantities in different units (for
example, if I'm transferring data at 100MB/s I don't want to print
this in bits / second).  All of these seems to only allow printing of
a quantity in its base unit, which here is defined to be bits.  I'd
like to be able to do something like:

quantity<capacity> q = 2180321.0 * bytes;
std::cout << q * megabytes << std::endl;

or slightly more complicated,

quantity<capacity> q = 1.432 * gigabytes;
quantity<time> t = 1.5 * hours;
std::cout << (q/t) * (megabytes/minute) << std::endl;
std::cout << (q/t) * (kilobytes/second) << std::endl;

and have it print:

2.07931614 MB for the first example,

and

16.2929778 MB / minute
278.066821 KB / second

for the second example

It seems like this should "just work" since I've defined them all as
scaled based units, but instead the first example just prints

1.74426e+007 b MB

which means all its doing is formatting it as bits and then appending "MB".

Is this possible short of making one system for each type I want to
convert between?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Zachary Turner wrote:

> On Thu, Jul 2, 2009 at 2:07 PM, Steven Watanabe<watanabesj@...> wrote:
>  
>> AMDG
>>
>> Zachary Turner wrote:
>>    
>>> Thanks for your help so far!  I know I'm probably just making this too
>>> difficult, but it's still not working.  I guess I should just post a
>>> complete sample so that we can eliminate the snip factor from the list
>>> of possible causes  (I put them in the boost namespace for the sake of
>>> consistency but the same problem arises regardless).
>>>
>>> <snip>
>>>  void foo()
>>> {
>>>        using boost::units::quantity;
>>>        using namespace boost::units::data_capacity;
>>>
>>>        //Both of these fail with the message that there is no
>>> conversion to the destination
>>>        //type because the construcor is explicit
>>>        quantity<data_capacity> compressed_size = 1000 * bytes;
>>>        quantity<data_capacity, int> compressed_size2 = 1000 * bytes;
>>>
>>>      
>> Implicit conversion between different units is not allowed.
>> Try
>> quantity<data_capacity> compressed_size(1000 * bytes);
>>    
>
> Thanks.  The confusion came from the fact that the syntax I was trying
> was being used in some of the examples.  But there is something
> different about those examples, so that's why it wasn't working.  One
> of the trig examples has a line:
>
> quantity<plane_angle>           theta = 0.375*radians;
>
> for example.   I suppose it's due to the fact that radians are the
> "primary" unit for this dimension?
>  

The difference is that plane_angle is the same unit as radians.
In your case, data_capacity is defined as bits, while you are
assigning it a value in bytes.  Since the units change, the conversion
is explicit.

> That aside, I still think something isn't exactly right.  Ultimately I
> need to be able to print these quantities in different units (for
> example, if I'm transferring data at 100MB/s I don't want to print
> this in bits / second).  All of these seems to only allow printing of
> a quantity in its base unit, which here is defined to be bits.  I'd
> like to be able to do something like:
>
> quantity<capacity> q = 2180321.0 * bytes;
> std::cout << q * megabytes << std::endl;
>  

The units of q are bits.  Thus, the units of the expression that
you are printing are bits * megabytes which is printed as "b MB"

> It seems like this should "just work" since I've defined them all as
> scaled based units, but instead the first example just prints
>
> 1.74426e+007 b MB
>
> which means all its doing is formatting it as bits and then appending "MB"

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Jul 2, 2009 at 3:41 PM, Steven Watanabe<watanabesj@...> wrote:

> Zachary Turner wrote:
>>
>> On Thu, Jul 2, 2009 at 2:07 PM, Steven Watanabe<watanabesj@...>
>> Thanks.  The confusion came from the fact that the syntax I was trying
>> was being used in some of the examples.  But there is something
>> different about those examples, so that's why it wasn't working.  One
>> of the trig examples has a line:
>>
>> quantity<plane_angle>           theta = 0.375*radians;
>>
>> for example.   I suppose it's due to the fact that radians are the
>> "primary" unit for this dimension?
>>
>
> The difference is that plane_angle is the same unit as radians.
> In your case, data_capacity is defined as bits, while you are
> assigning it a value in bytes.  Since the units change, the conversion
> is explicit.

Well what then do you think is the "correct" or "best" way to support
what I'm trying to do?  It seems like a fairly simple use case but at
least to me anyway it's turning out to be rather confusing and
complicated.  For example, quantity<> is defined as

template<class Unit> class quantity;

yet one of the valid values for Unit is boost::units::dimensionless.
So are we specifying a unit or a dimension?  Clearly something that is
dimensionless is also unitless but it seems inconsistent for values to
be either units, or the empty dimension.

The examples have many occurences of things such as
quantity<si::length>, quantity<si::mass>, quantity<temperature>, all
of which in a physical sense are dimensions.  feet,yards,meters;
kilograms, grams, ounces; fahrenheit, celsius, kelvin are all units.
So I would expect to see quantity<fahrenheit>, quantity<ounces>,
quantity<inches>, just based on the fact that the template argument is
named Unit.

However, all of the examples seem to define only 1 valid template
argument for quantity per dimension per system.  So if you want si
mass then there's 1 thing you can pass to quantity<>, even though with
all the prefixes there are a multitude of different units for mass
that are still based on the si system.

I agree that the template argument to quantity should be a unit, but
then I would expect to be able to declare a quantity<> parameterized
with every possible unit of length measurement, quantity<feet>,
quantity<inches>, quantity<mm>, etc.  with automatic conversions
provided between every combination.


Maybe I'm just doing it all wrong, I'm not trying to be a PITA or
anything, at this point I really just want it to work :(


Maybe units of data storage capacity could be incorporated into boost
1.40 since they're pretty common (especially for programmers),
although ultimately it would still be nice if I could understand how
to use the library.


Thanks for your patience :)
Zach
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Zachary Turner wrote:

> On Thu, Jul 2, 2009 at 3:41 PM, Steven Watanabe<watanabesj@...> wrote:
>  
>> Zachary Turner wrote:
>>    
>>> On Thu, Jul 2, 2009 at 2:07 PM, Steven Watanabe<watanabesj@...>
>>> Thanks.  The confusion came from the fact that the syntax I was trying
>>> was being used in some of the examples.  But there is something
>>> different about those examples, so that's why it wasn't working.  One
>>> of the trig examples has a line:
>>>
>>> quantity<plane_angle>           theta = 0.375*radians;
>>>
>>> for example.   I suppose it's due to the fact that radians are the
>>> "primary" unit for this dimension?
>>>
>>>      
>> The difference is that plane_angle is the same unit as radians.
>> In your case, data_capacity is defined as bits, while you are
>> assigning it a value in bytes.  Since the units change, the conversion
>> is explicit.
>>    
>
> Well what then do you think is the "correct" or "best" way to support
> what I'm trying to do?  It seems like a fairly simple use case but at
> least to me anyway it's turning out to be rather confusing and
> complicated.  For example, quantity<> is defined as
>
> template<class Unit> class quantity;
>
> yet one of the valid values for Unit is boost::units::dimensionless.
>  

I don't think that there is a boost::units::dimensionless.
There is a boost::units::si::dimensionless, though.

> So are we specifying a unit or a dimension?  Clearly something that is
> dimensionless is also unitless but it seems inconsistent for values to
> be either units, or the empty dimension.
>
> The examples have many occurences of things such as
> quantity<si::length>, quantity<si::mass>, quantity<temperature>, all
> of which in a physical sense are dimensions.  feet,yards,meters;
> kilograms, grams, ounces; fahrenheit, celsius, kelvin are all units.
> So I would expect to see quantity<fahrenheit>, quantity<ounces>,
> quantity<inches>, just based on the fact that the template argument is
> named Unit.
>  

In general you should read boost::units::si::length as the unit of length in
the si system.

> However, all of the examples seem to define only 1 valid template
> argument for quantity per dimension per system.  So if you want si
> mass then there's 1 thing you can pass to quantity<>, even though with
> all the prefixes there are a multitude of different units for mass
> that are still based on the si system.
>  

The official SI unit of mass is kilograms.
The si system represents a unique set of units.

> I agree that the template argument to quantity should be a unit, but
> then I would expect to be able to declare a quantity<> parameterized
> with every possible unit of length measurement, quantity<feet>,
> quantity<inches>, quantity<mm>, etc.  with automatic conversions
> provided between every combination.
>  

The conversions are provided.  They are not implicit.

> Maybe I'm just doing it all wrong, I'm not trying to be a PITA or
> anything, at this point I really just want it to work :(
>
>
> Maybe units of data storage capacity could be incorporated into boost
> 1.40 since they're pretty common (especially for programmers),
> although ultimately it would still be nice if I could understand how
> to use the library.
>  

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: Units of data

by Matthias Schabel-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Just to be concrete, I've reworked your code a bit to eliminate  
extraneous complexity :

#include <iostream>

#include <boost/units/base_dimension.hpp>
#include <boost/units/base_unit.hpp>
#include <boost/units/io.hpp>
#include <boost/units/scale.hpp>
#include <boost/units/scaled_base_unit.hpp>
#include <boost/units/make_system.hpp>
#include <boost/units/static_constant.hpp>
#include <boost/units/quantity.hpp>

#define DECLARE_BASE_UNIT_INFO(base_unit_, name_, symbol_) \
template<> struct base_unit_info<base_unit_> { \
        static const char* name() { return name_; } \
        static const char* symbol() { return symbol_; } \
};

namespace boost {

namespace units {

struct data_capacity_base_dimension :  
base_dimension<data_capacity_base_dimension, 73254> {};
typedef data_capacity_base_dimension::dimension_type  
data_capacity_dimension;

struct bit_base_unit :  
base_unit<bit_base_unit,data_capacity_dimension, 76389> {};

typedef scaled_base_unit<bit_base_unit, scale<2, static_rational<3> >  
 >     byte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<10>  
 > >   kilobyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<20>  
 > >   megabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<30>  
 > >   gigabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<40>  
 > >   terabyte_base_unit;
typedef scaled_base_unit<byte_base_unit, scale<2, static_rational<50>  
 > >   petabyte_base_unit;

DECLARE_BASE_UNIT_INFO(bit_base_unit, "bit", "b")
DECLARE_BASE_UNIT_INFO(byte_base_unit, "byte", "B")
DECLARE_BASE_UNIT_INFO(kilobyte_base_unit, "kilobyte", "KB")
DECLARE_BASE_UNIT_INFO(megabyte_base_unit, "megabyte", "MB")
DECLARE_BASE_UNIT_INFO(gigabyte_base_unit, "gigabyte", "GB")
DECLARE_BASE_UNIT_INFO(terabyte_base_unit, "terabyte", "TB")
DECLARE_BASE_UNIT_INFO(petabyte_base_unit, "petabyte", "PB")

BOOST_UNITS_STATIC_CONSTANT(bit, bit_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(bits, bit_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(byte, byte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(bytes, byte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(kilobyte, kilobyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(kilobytes, kilobyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(megabyte, megabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(megabytes, megabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(gigabyte, gigabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(gigabytes, gigabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(terabyte, terabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(terabytes, terabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(petabyte, petabyte_base_unit::unit_type);
BOOST_UNITS_STATIC_CONSTANT(petabytes, petabyte_base_unit::unit_type);

}
}

using namespace boost::units;

template<class U,class Y>
void outputDataCapacity(const quantity<U,Y>& q)
{
     static const Y  bits_per_byte = 8,
                     bits_per_kilobyte = 8*1024,
                     bits_per_megabyte = 8*1024*1024,
                     bits_per_gigabyte = 8*1024*1024*1024;

     const quantity<bit_base_unit::unit_type,Y>  qb(q);
     const Y                                     qv(qb.value());

     if (qb.value() <= bits_per_byte)
         std::cout << qb << std::endl;
     else if (qb.value() <= bits_per_kilobyte)
         std::cout << quantity<byte_base_unit::unit_type,Y>(q) <<  
std::endl;
     else if (qb.value() <= bits_per_megabyte)
         std::cout << quantity<kilobyte_base_unit::unit_type,Y>(q) <<  
std::endl;
     else if (qb.value() <= bits_per_gigabyte)
         std::cout << quantity<megabyte_base_unit::unit_type,Y>(q) <<  
std::endl;
     else
         std::cout << "error..." << std::endl;

     return;
}

int main()
{
        quantity<bit_base_unit::unit_type, int>         c1(1000 * bits);
        quantity<byte_base_unit::unit_type, int>        c2(1000 * bytes);
        quantity<kilobyte_base_unit::unit_type, int>    c3(1000 * kilobytes);
        quantity<megabyte_base_unit::unit_type, int>    c4(1000 * megabytes);

        quantity<bit_base_unit::unit_type, int>         d1(1 * gigabyte);
        quantity<byte_base_unit::unit_type, int>        d2(1 * gigabyte);
        quantity<kilobyte_base_unit::unit_type, int>    d3(1 * gigabyte);
        quantity<megabyte_base_unit::unit_type, int>    d4(1 * gigabyte);

     std::cout << c1 << std::endl;
     std::cout << c2 << std::endl;
     std::cout << c3 << std::endl;
     std::cout << c4 << std::endl;
     std::cout << std::endl;

     std::cout << d1 << std::endl;
     std::cout << d2 << std::endl;
     std::cout << d3 << std::endl;
     std::cout << d4 << std::endl;
     std::cout << std::endl;

     for (double v=1.0;v<=std::pow(2.0,24);v*=2.0)
     {
         outputDataCapacity(v*bits);
     }

     return 0;
}

This code compiles and runs correctly and does what you would expect,  
outputting :

1000 b
1000 B
1000 KB
1000 MB

2147483647 b
1073741824 B
1048576 KB
1024 MB

1 b
2 b
4 b
8 b
2 B
4 B
8 B
16 B
32 B
64 B
128 B
256 B
512 B
1024 B
2 KB
4 KB
8 KB
16 KB
32 KB
64 KB
128 KB
256 KB
512 KB
1024 KB
error...

The conceptual problem that you're having is wanting the program to  
somehow "know" that you want a quantity that is represented in bits to  
be output as megabytes. However, while the program knows that those  
units are convertible, there is no way for it to know that you want  
megabytes instead of gigabytes, kilobytes, or any other unit for which  
the conversion is defined. Thus, if you want specific output  
formatting, you need to do it yourself like I've done in  
outputDataCapacity...

Hope this helps.

Matthias



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost