From: si-units-list@si-units (si-units-digest)
To: si-units-digest@si-units
Subject: si-units-digest V1 #9
Reply-To: si-units-list@si-units
Sender: si-units-list@si-units
Errors-To: si-units-list@si-units
Precedence: bulk
si-units-digest Sunday, September 1 2002 Volume 01 : Number 009
In this issue:
SI Units Project: Nesting expression templates (C++)
Re: SI Units Project: Nesting expression templates (C++)
Re: SI Units Project: Nesting expression templates (C++)
Re: SI Units Project: -- can compile...
Re: SI Units Project: -- can compile...
SI Units Project: Abstract base class (C++)
Re: SI Units Project: Abstract base class (C++)
RE: SI Units Project: Abstract base class (C++)
Re: SI Units Project: Abstract base class (C++)
Re: SI Units Project: Abstract base class (C++)
----------------------------------------------------------------------
Date: Tue, 23 Jul 2002 11:19:41 +0100
From: "Watts, Simon (UK)"
Subject: SI Units Project: Nesting expression templates (C++)
Just a few thoughts on expression templates, to see if I am on the right
lines...
Considering item T2 in the requirements doc [1], on efficiency of computing
with Units wrt their underlying data types.
What if the data type uses expression templates? (eg, Blitz++ [2]). Do we
need to implement expression templates for out Units classes/template, and
does this nest propertly with another impliementation?
Without expression templates, does the return type get in the way?
For instance (hiding the templates...):
inline UnitAB
operator* (const UnitA& u, const UnitB& v)
{
return UnitAB( u.m * v.m ); // m is magnitude, a data_type
value
}
If we then have an expression:
UnitABCD y = u * v * w * x;
- -> = (((u * v) * w) * x);
- -> = UnitABCD (UnitABC (UnitAB (u.m * v.m).m * w.m).m * x.m)
Which, unless the compiler is very clever, probably breaks the expression
templates on the data_type elements??? Is this right?
For data_type's expression templates to work, our expression templates on
Units would have to expand the inline to:
= UnitABCD (u.m * v.m * w.m * x.m);
Which is do-able, if our expression templates have a method like:
inline data_type eval () { return rhs.eval () * lhs.eval (); }
and a seperate typecast operator:
inline operator UnitABCD () { return UnitABCD (eval ()); }
I really need to play around with expression templates before considering
how to implement them for this case. Fortunately, there is the hairy
problem of pretty-printing unit symbols to deal with first...
Si.
[1]
http://homepage.ntlworld.com/mark.easterbrook/mentored/Requirements2.txt)
[2] http://www.oonumerics.org/blitz/
------------------------------
Date: Wed, 24 Jul 2002 22:55:24 -0700
From: Pete and Lana Klier
Subject: Re: SI Units Project: Nesting expression templates (C++)
I'll try to get back to this on the weekend... sounds like some interesting
issues to hammer out....
Watts, Simon (UK) wrote:
> Just a few thoughts on expression templates, to see if I am on the right
> lines...
>
> Considering item T2 in the requirements doc [1], on efficiency of computing
> with Units wrt their underlying data types.
>
> What if the data type uses expression templates? (eg, Blitz++ [2]). Do we
> need to implement expression templates for out Units classes/template, and
> does this nest propertly with another impliementation?
>
> Without expression templates, does the return type get in the way?
>
> For instance (hiding the templates...):
> inline UnitAB
> operator* (const UnitA& u, const UnitB& v)
> {
> return UnitAB( u.m * v.m ); // m is magnitude, a data_type
> value
> }
>
> If we then have an expression:
>
> UnitABCD y = u * v * w * x;
> -> = (((u * v) * w) * x);
> -> = UnitABCD (UnitABC (UnitAB (u.m * v.m).m * w.m).m * x.m)
>
> Which, unless the compiler is very clever, probably breaks the expression
> templates on the data_type elements??? Is this right?
>
> For data_type's expression templates to work, our expression templates on
> Units would have to expand the inline to:
> = UnitABCD (u.m * v.m * w.m * x.m);
>
> Which is do-able, if our expression templates have a method like:
> inline data_type eval () { return rhs.eval () * lhs.eval (); }
> and a seperate typecast operator:
> inline operator UnitABCD () { return UnitABCD (eval ()); }
>
> I really need to play around with expression templates before considering
> how to implement them for this case. Fortunately, there is the hairy
> problem of pretty-printing unit symbols to deal with first...
>
> Si.
>
> [1]
> http://homepage.ntlworld.com/mark.easterbrook/mentored/Requirements2.txt)
> [2] http://www.oonumerics.org/blitz/
------------------------------
Date: Sat, 27 Jul 2002 22:34:36 -0700
From: Pete and Lana Klier
Subject: Re: SI Units Project: Nesting expression templates (C++)
If I understand the context, we may be also talking about requirement C9
about unrestricted temporaries; possible also C12, conversion between
underlying numeric types, as well as requirements about minimum syntax and
our data types usable in any context.
Basically, any system that can handle user-defined data types should be
able to handle the SI units type-system, and if everything in our system
is implemented as templates, then everybody should be happy with it.
However, some systems may be making some assumptions that would
be violated by the SI type system in the data types of temporaries. For
instance, it is no longer true that the type of T squared is the same as T.
Suppose that the Blitz (or standard template) supplied data type "Vector"
has a magnitude operator (I am assuming a representation for illustrative
purposes) , i.e.
template class Vector
{
private:
T *v_;
int len_;
public:
.... blah blah.....
T magnitude (void) const
{
T sum = 0;
for(int i = 0; i < len_; i++) sum += v_[0] * v_[0];
return sqrt(sum);
}
}
and usage
Vector> foo ;
... etc etc ...
ohms foo_magnitude = foo.magnitude();
the magnitude operator will expand ingo
ohms magnitude (void) const
{
ohms sum = 0;
for(int i = 0; i < len_;i++) sum += v_[0] * v_[0];
return sqrt(sum):
}
Assuming that I can always use zero on the right-hand-side to initialize the
sum, and that
the square root operator is implemented, then the problem is that the
implementor of
"magnitude" made the assumption that the type of the square of T is the same
as the
type of T for temporaries!!! This assumption may have been justified in the
past, i.e.
is true for "double" and "complex". Thus the "magnitude" method might have
to be
re-implemented as something like:
template class Vector
{
... etc. etc.
public:
template T magnitude (void) const
{
U sum = 0;
for(int i = 0; i < len_; i++) sum += v_[0] * v_[0];
return sqrt(sum);
}
}
Then, if the compiler is smart, and/or the user is smart, then this might
automatically 'unify' to what we need -- U would unify to ohms-squared
in the above example and the world would be happy. Naturally if we were
just given a library then a special-purpose "magnitude" might need to be
written by inheritance (perhaps just by stripping off the data types) --
perhaps with the proper bit of overloading it might even have the same
name.
Another way to do it might be to encapsulate the type *within* the SI units
system, i.e.
ohms> vec_ohms ;
...etc...
ohms mag_ohms = vec_ohms.magnitude();
The obstacle here is that there is no "magnitude" operator (yet) within
the SI units system. With inheritance it would be an easy extension
to the SI units system to add "magnitude" (or any other method)
which, given an object of type V, returns an object of type W. Even if
for vectors it would be possible to extend, we could think about the
magnitude of a "complex" which is "double." -- in our case the magnitude
of ohms would be ohms. In such a case, we didn't
think of every possible operator -- and couldn't, in advance, because we
don't know what everyone is going to call things.
Thus, if th SI units library were to be put together with some other library,
some extensibility or customization of one or the other may be required --
for instance, getting people to admit that the type of the square of X isn't
necessarily the same as the type of X! In the case of the SI units library,
we would need to admit that more things than "+", "-", "*", "/", "/=", etc.
etc.
exist in the universe. This shouldn't be too difficult with a combination of
templates and inheritance,
If we can forgo the object syntax such as foo.magnitude() for something
like magnitude(foo). Then you can just write a template -- I did that
for my version of operator * anyway.
To avoid the syntax, combining templates and inheritance in
a way that I haven't figured out yet (but may be similar to my
"mksunity" declaration if the templates can unify).
In any case, I can see a few new requirements here. But the implementors
of numeric libraries will also have to adapt!
Watts, Simon (UK) wrote:
> Just a few thoughts on expression templates, to see if I am on the right
> lines...
>
> Considering item T2 in the requirements doc [1], on efficiency of computing
> with Units wrt their underlying data types.
>
> What if the data type uses expression templates? (eg, Blitz++ [2]). Do we
> need to implement expression templates for out Units classes/template, and
> does this nest propertly with another impliementation?
>
> Without expression templates, does the return type get in the way?
>
> For instance (hiding the templates...):
> inline UnitAB
> operator* (const UnitA& u, const UnitB& v)
> {
> return UnitAB( u.m * v.m ); // m is magnitude, a data_type
> value
> }
>
> If we then have an expression:
>
> UnitABCD y = u * v * w * x;
> -> = (((u * v) * w) * x);
> -> = UnitABCD (UnitABC (UnitAB (u.m * v.m).m * w.m).m * x.m)
>
> Which, unless the compiler is very clever, probably breaks the expression
> templates on the data_type elements??? Is this right?
>
> For data_type's expression templates to work, our expression templates on
> Units would have to expand the inline to:
> = UnitABCD (u.m * v.m * w.m * x.m);
>
> Which is do-able, if our expression templates have a method like:
> inline data_type eval () { return rhs.eval () * lhs.eval (); }
> and a seperate typecast operator:
> inline operator UnitABCD () { return UnitABCD (eval ()); }
>
> I really need to play around with expression templates before considering
> how to implement them for this case. Fortunately, there is the hairy
> problem of pretty-printing unit symbols to deal with first...
>
> Si.
>
> [1]
> http://homepage.ntlworld.com/mark.easterbrook/mentored/Requirements2.txt)
> [2] http://www.oonumerics.org/blitz/
------------------------------
Date: Sun, 28 Jul 2002 09:45:51 -0700
From: Pete and Lana Klier
Subject: Re: SI Units Project: -- can compile...
I have unzipped and compiled Simon's code with g++-2.95.2.
Has anyone else had any luck getting that code up and running?
Pete and Lana Klier wrote:
> If I understand the context, we may be also talking about requirement C9
> about unrestricted temporaries; possible also C12, conversion between
> underlying numeric types, as well as requirements about minimum syntax and
> our data types usable in any context.
>
> Basically, any system that can handle user-defined data types should be
> able to handle the SI units type-system, and if everything in our system
> is implemented as templates, then everybody should be happy with it.
>
> However, some systems may be making some assumptions that would
> be violated by the SI type system in the data types of temporaries. For
> instance, it is no longer true that the type of T squared is the same as T.
>
> Suppose that the Blitz (or standard template) supplied data type "Vector"
> has a magnitude operator (I am assuming a representation for illustrative
> purposes) , i.e.
>
> template class Vector
> {
> private:
> T *v_;
> int len_;
>
> public:
>
> .... blah blah.....
>
> T magnitude (void) const
> {
> T sum = 0;
> for(int i = 0; i < len_; i++) sum += v_[0] * v_[0];
> return sqrt(sum);
> }
>
> }
>
> and usage
>
> Vector> foo ;
> ... etc etc ...
>
> ohms foo_magnitude = foo.magnitude();
>
> the magnitude operator will expand ingo
>
> ohms magnitude (void) const
> {
> ohms sum = 0;
> for(int i = 0; i < len_;i++) sum += v_[0] * v_[0];
> return sqrt(sum):
> }
>
> Assuming that I can always use zero on the right-hand-side to initialize the
> sum, and that
> the square root operator is implemented, then the problem is that the
> implementor of
> "magnitude" made the assumption that the type of the square of T is the same
> as the
> type of T for temporaries!!! This assumption may have been justified in the
> past, i.e.
> is true for "double" and "complex". Thus the "magnitude" method might have
> to be
> re-implemented as something like:
>
> template class Vector
> {
> ... etc. etc.
>
> public:
>
> template T magnitude (void) const
> {
> U sum = 0;
> for(int i = 0; i < len_; i++) sum += v_[0] * v_[0];
> return sqrt(sum);
> }
>
> }
>
> Then, if the compiler is smart, and/or the user is smart, then this might
> automatically 'unify' to what we need -- U would unify to ohms-squared
> in the above example and the world would be happy. Naturally if we were
> just given a library then a special-purpose "magnitude" might need to be
> written by inheritance (perhaps just by stripping off the data types) --
> perhaps with the proper bit of overloading it might even have the same
> name.
>
> Another way to do it might be to encapsulate the type *within* the SI units
> system, i.e.
>
> ohms> vec_ohms ;
>
> ...etc...
>
> ohms mag_ohms = vec_ohms.magnitude();
>
> The obstacle here is that there is no "magnitude" operator (yet) within
> the SI units system. With inheritance it would be an easy extension
> to the SI units system to add "magnitude" (or any other method)
> which, given an object of type V, returns an object of type W. Even if
> for vectors it would be possible to extend, we could think about the
> magnitude of a "complex" which is "double." -- in our case the magnitude
> of ohms would be ohms. In such a case, we didn't
> think of every possible operator -- and couldn't, in advance, because we
> don't know what everyone is going to call things.
>
> Thus, if th SI units library were to be put together with some other library,
> some extensibility or customization of one or the other may be required --
> for instance, getting people to admit that the type of the square of X isn't
> necessarily the same as the type of X! In the case of the SI units library,
> we would need to admit that more things than "+", "-", "*", "/", "/=", etc.
> etc.
> exist in the universe. This shouldn't be too difficult with a combination of
>
> templates and inheritance,
> If we can forgo the object syntax such as foo.magnitude() for something
> like magnitude(foo). Then you can just write a template -- I did that
> for my version of operator * anyway.
>
> To avoid the syntax, combining templates and inheritance in
> a way that I haven't figured out yet (but may be similar to my
> "mksunity" declaration if the templates can unify).
>
> In any case, I can see a few new requirements here. But the implementors
> of numeric libraries will also have to adapt!
>
> Watts, Simon (UK) wrote:
>
> > Just a few thoughts on expression templates, to see if I am on the right
> > lines...
> >
> > Considering item T2 in the requirements doc [1], on efficiency of computing
> > with Units wrt their underlying data types.
> >
> > What if the data type uses expression templates? (eg, Blitz++ [2]). Do we
> > need to implement expression templates for out Units classes/template, and
> > does this nest propertly with another impliementation?
> >
> > Without expression templates, does the return type get in the way?
> >
> > For instance (hiding the templates...):
> > inline UnitAB
> > operator* (const UnitA& u, const UnitB& v)
> > {
> > return UnitAB( u.m * v.m ); // m is magnitude, a data_type
> > value
> > }
> >
> > If we then have an expression:
> >
> > UnitABCD y = u * v * w * x;
> > -> = (((u * v) * w) * x);
> > -> = UnitABCD (UnitABC (UnitAB (u.m * v.m).m * w.m).m * x.m)
> >
> > Which, unless the compiler is very clever, probably breaks the expression
> > templates on the data_type elements??? Is this right?
> >
> > For data_type's expression templates to work, our expression templates on
> > Units would have to expand the inline to:
> > = UnitABCD (u.m * v.m * w.m * x.m);
> >
> > Which is do-able, if our expression templates have a method like:
> > inline data_type eval () { return rhs.eval () * lhs.eval (); }
> > and a seperate typecast operator:
> > inline operator UnitABCD () { return UnitABCD (eval ()); }
> >
> > I really need to play around with expression templates before considering
> > how to implement them for this case. Fortunately, there is the hairy
> > problem of pretty-printing unit symbols to deal with first...
> >
> > Si.
> >
> > [1]
> > http://homepage.ntlworld.com/mark.easterbrook/mentored/Requirements2.txt)
> > [2] http://www.oonumerics.org/blitz/
------------------------------
Date: Mon, 29 Jul 2002 18:32:59 +0000
From: Mark Easterbrook
Subject: Re: SI Units Project: -- can compile...
Pete and Lana Klier wrote:
>
> I have unzipped and compiled Simon's code with g++-2.95.2.
>
> Has anyone else had any luck getting that code up and running?
>
I have not found time to try. The weather is fantastic here so I
am spending most of my free time out in the garden instead of in
front of the computer :)
I suspect others are doing similar as the traffic is quite light!
The papers are predicting summer will end on Thursday! Maybe some
heavy rain will drive me back to the computer (and help the parched
garden).
- --
mark@si-units
------------------------------
Date: Tue, 13 Aug 2002 12:43:57 +0100
From: "Watts, Simon (UK)"
Subject: SI Units Project: Abstract base class (C++)
Hm, been quiet here for a while -- folks off enjoying the summer? Well,
thought I'd drop a thought in while I sit waiting for stuff to compile...
I have just been musing over whether it is desirable or possible to have an
abstract base class for dimesioned data types.
The motivation is that it would be 'nice' to allow the handing of
dimensioned data without requiring without reference to its dimensionality.
For example, where intermediate types are produced as part of an equation.
I am assuming the dimensioned data is defined something like:
// abstract base class
class UB;
// templated on dimensionality
template
class UT : public UB;
So than data can be handled as references to UB.
But I am currently stumped at how to resolve the true types of two base
class references for arithmetic operations. For instance:
template
UT::type>
operator+ &, const UT&);
void foo (const UB& a, const UB& b)
{
cout << a + b << endl;
}
int main ()
{
UT c;
UT d;
foo (c,d);
}
((a dumb example I know, but its only to illustrate!))
Then the addition in the call to foo() must resolved to:
operator+ (const UT&, const UT&)
Will the compiler propertly resolved the true type of references in
determining function calls? I suspect not (at least, its not something I
have ever relied on...).
I have looked at double dispatch (briefly), but the reference I had did not
consider templated derived classes.
Is this method/function call resolution possible?
Is providing an abstract base class useful? I think it is, but only if it
does not break the compile-time dimensional analysis.
An alternative to an abstrace base would be an envelope class, but I suspect
that will run into the same problems.
SAW.
------------------------------
Date: Wed, 14 Aug 2002 12:13:39 +0000
From: Mark Easterbrook
Subject: Re: SI Units Project: Abstract base class (C++)
"Watts, Simon (UK)" wrote:
>
> Hm, been quiet here for a while -- folks off enjoying the summer? Well,
> thought I'd drop a thought in while I sit waiting for stuff to compile...
>
As most of our members live in Northern Hemisphere countries with
August as the main holiday season I assume holidays and summer
weather account for the low traffic.
I have been so busy socially I have had so little time for anything,
the little free time I have found related to computers has been
fixing my mis-behaving server (I think one of the Pentium III CPUs
was the problem - it is now been banished to a anti-static bag
without bail awaiting trial). Of course all CPUs have to be
identical speed+multiplier so if anyone knows somewhere in the UK
that still sells 700MHz Pentium III FC-PGAs please let me know,
otherwise
it will have to stay one CPU short. :(
------------------------------
Date: Fri, 16 Aug 2002 11:41:06 +0100
From: "Watts, Simon (UK)"
Subject: RE: SI Units Project: Abstract base class (C++)
Further thoughts on this...
Probably not a good idea in terms of efficiency, since it requires the
introduction of polymorphism -- ie virtual functions -- which then has, as
Simon Sebright just pointed out on accu-general (unconnected threat), a
~4byte increase in size per instance (yeh, I knew this, just hadnt
considered it in this context yet).
In most applications our unit types contain just a primative value, so this
is a large percentage increase in memory requirements (say, +100% for float,
+50% for double data types).
Also, I havent seen an implementation of double dispatch of templated
classes, and can't think of a non-trival way to do this.
So I guess the abstract base class for dimensioned units is a non-starter,
at least with the template/compile-time dimension analysis implimentation.
Of course, it isnt necessary in the context of run-time dim analysis
implimentations.
SAW.
------------------------------
Date: Mon, 19 Aug 2002 17:02:40 -0700
From: Pete and Lana Klier
Subject: Re: SI Units Project: Abstract base class (C++)
You bet. We just got back from a long vacation.
Mark Easterbrook wrote:
> "Watts, Simon (UK)" wrote:
> >
> > Hm, been quiet here for a while -- folks off enjoying the summer? Well,
> > thought I'd drop a thought in while I sit waiting for stuff to compile...
> >
>
> As most of our members live in Northern Hemisphere countries with
> August as the main holiday season I assume holidays and summer
> weather account for the low traffic.
>
> I have been so busy socially I have had so little time for anything,
> the little free time I have found related to computers has been
> fixing my mis-behaving server (I think one of the Pentium III CPUs
> was the problem - it is now been banished to a anti-static bag
> without bail awaiting trial). Of course all CPUs have to be
> identical speed+multiplier so if anyone knows somewhere in the UK
> that still sells 700MHz Pentium III FC-PGAs please let me know,
> otherwise
> it will have to stay one CPU short. :(
------------------------------
Date: Sat, 31 Aug 2002 17:35:41 -0700
From: Pete and Lana Klier
Subject: Re: SI Units Project: Abstract base class (C++)
The day job has been keeping me busy, but it should
be reduced in workload in a couple of weeks. Hopefully
we will be able to get back on track soon. Any new
developments out there??
I may need to tinker a little bit before I am up to snuff on
metaprogramming.
Pete and Lana Klier wrote:
> You bet. We just got back from a long vacation.
>
> Mark Easterbrook wrote:
>
> > "Watts, Simon (UK)" wrote:
> > >
> > > Hm, been quiet here for a while -- folks off enjoying the summer? Well,
> > > thought I'd drop a thought in while I sit waiting for stuff to compile...
> > >
> >
> > As most of our members live in Northern Hemisphere countries with
> > August as the main holiday season I assume holidays and summer
> > weather account for the low traffic.
> >
> > I have been so busy socially I have had so little time for anything,
> > the little free time I have found related to computers has been
> > fixing my mis-behaving server (I think one of the Pentium III CPUs
> > was the problem - it is now been banished to a anti-static bag
> > without bail awaiting trial). Of course all CPUs have to be
> > identical speed+multiplier so if anyone knows somewhere in the UK
> > that still sells 700MHz Pentium III FC-PGAs please let me know,
> > otherwise
> > it will have to stay one CPU short. :(
------------------------------
End of si-units-digest V1 #9
****************************