caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Dimensional Analysis question
@ 2014-10-16 16:37 Shayne Fletcher
  2014-10-16 17:21 ` Octachron
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Shayne Fletcher @ 2014-10-16 16:37 UTC (permalink / raw)
  To: caml-list@inria.fr users

[-- Attachment #1: Type: text/plain, Size: 5173 bytes --]

Dear OCamlers,

In 1994, Barton and Nackman in their book 'Scientific Engineering in
C++' [1] demonstrated how one could encode the rules of Dimensional
Analysis [2] into the C++ type system enabling compile-time checking
(no runtime-cost) of the plausibility (at least up to the dimensional
correctness) of computations.

In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3]
showed the Barton Nackman technique to be elegantly implementable
using compile time type sequences encoding integer constants. At the
end of this post, I provide a complete listing of their example
program [4].

The key properties of the system (as I see it) are:
  - Encoding of integers as types;
  - Compile time manipulation of sequences of these integer encodings
    to deduce/produce new derived types.

Now, it is not immediately obvious to me how to approach this problem
in OCaml. It irks me some that I can't immediately produce a yet more
elegant OCaml program for this problem and leaves me feeling like C++
has "got something over on us" here ;)

My question therefore is: Does anyone have suggestions/pointers
on how to approach automatic dimensional analysis via the OCaml type
system?

Best,

-- 
Shayne Fletcher

[1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++:
    an Introduction with Advanced Techniques and Examples. Reading,
    MA: Addison Wesley. ISBN 0-201-53393-6. 1994.

[2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis

[3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming:
    Concepts, Tools, and Techniques from Boost and Beyond (C++ in
    Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004.

[4] Code listing:

    //"c:/program files (x86)/Microsoft Visual Studio
10.0/vc/vcvarsall.bat" x64
    //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp

    #include <boost/mpl/vector_c.hpp>
    #include <boost/mpl/transform.hpp>
    #include <boost/mpl/placeholders.hpp>
    #include <boost/mpl/equal.hpp>
    #include <boost/mpl/plus.hpp>
    #include <boost/mpl/minus.hpp>
    #include <boost/static_assert.hpp>

    typedef boost::mpl::vector_c<int,1,0,0,0,0,0,0> mass;
    typedef boost::mpl::vector_c<int,0,1,0,0,0,0,0> length;
    typedef boost::mpl::vector_c<int,0,0,1,0,0,0,0> time;
    typedef boost::mpl::vector_c<int,0,0,0,1,0,0,0> charge;
    typedef boost::mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
    typedef boost::mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
    typedef boost::mpl::vector_c<int,0,0,0,0,0,0,1> angle;
    typedef boost::mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;     // l/t
    typedef boost::mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // l/(t2)
    typedef boost::mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;     // ml/t
    typedef boost::mpl::vector_c<int,1,1,-2,0,0,0,0> force;        //
ml/(t2)
    typedef boost::mpl::vector_c<int,0,0,0,0,0,0,0> scalar;

    template <class T, class Dimensions>
    class quantity
    {
    public:
      explicit quantity (T val)
        : val (val)
      {}
      template <class OtherDimensions>
      quantity (quantity<T, OtherDimensions> const& other)
        : val (other.value ()) {
        BOOST_MPL_ASSERT( (boost::mpl::equal<Dimensions, OtherDimensions>));
      }
      T value () const { return val; }
    private:
      T val;
    };

    template <class T, class D>
    quantity<T, D>
    operator + (quantity<T, D> x, quantity<T, D> y )
    {
      return quantity<T, D>(x.value () + y.value ());
    }

    template <class T, class D>
    quantity<T, D>
    operator - (quantity<T, D> x, quantity<T, D> y )
    {
      return quantity<T, D>(x.value () - y.value ());
    }

    template <class T, class D1, class D2>
    quantity <
      T
    , typename boost::mpl::transform<
        D1, D2, boost::mpl::plus<
                  boost::mpl::placeholders::_1
                , boost::mpl::placeholders::_2> >::type
    >
    operator* (quantity<T, D1> x, quantity <T, D2> y)
    {
      typedef typename boost::mpl::transform<
        D1, D2, boost::mpl::plus<
                  boost::mpl::placeholders::_1
                  , boost::mpl::placeholders::_2> >::type D;

      return quantity<T, D> (x.value () * y.value ());
    }

    template <class T, class D1, class D2>
    quantity <
      T
    , typename boost::mpl::transform<
        D1, D2, boost::mpl::minus<
                  boost::mpl::placeholders::_1
                , boost::mpl::placeholders::_2> >::type
    >
    operator/ (quantity<T, D1> x, quantity <T, D2> y)
    {
      typedef typename boost::mpl::transform<
        D1, D2, boost::mpl::minus<
                  boost::mpl::placeholders::_1
                  , boost::mpl::placeholders::_2> >::type D;

      return quantity<T, D> (x.value () / y.value ());
    }

    // -- test

    #include <iostream>
    #include <limits>
    #include <cassert>

    int main ()
    {
      quantity<float, mass> m (5.0f);
      quantity<float, acceleration> a(9.8f);
      quantity<float, force> f = m * a;
      quantity<float, mass> m2 = f / a;

      assert ((std::abs ((m2 - m).value ())) <=
std::numeric_limits<double>::epsilon ());

      return 0;
    }

[-- Attachment #2: Type: text/html, Size: 17886 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
@ 2014-10-16 17:21 ` Octachron
  2014-10-16 17:35 ` Mario Alvarez Picallo
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Octachron @ 2014-10-16 17:21 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 7239 bytes --]

Hello,
As far as I know it is possible to do some kind of basic dimensional 
analysis.

The idea is to encode natural number at the type level as
0 :: 'a -> 'a
1:: 'a -> 'a succ
n :: 'a -> 'a succ .... succ  (with n succ)

In other words, we are encoding translation on natural numbers rather 
than the natural numbers themselves.
The free parameter 'a allows to type addition and substraction. We can 
then define numbers with unit as a phantom type

type 'a t = float

and for instance a meter function as

let m : float ->  < m : 'a -> 'a > t = fun x -> x

where the row type is merely used to have nice label for the type name.

Addition and substraction then preserve the phantom type
val + : 'a t -> 'a t -> 'a t

whereas  multiplication and division use the free type parameter in the 
natural encoding to perform the addition

let ( * ) : <m : 'inf -> 'mid > t -> <m: 'mid -> 'sup> t -> <m: 'inf -> 
'sup> t = *.
let (/):  < m: inf->sup > t -> <m:inf->mid> t -> <m: mid-> sup>  t = ( /. )

This solution works for basic use but falls apart in complex use due to 
the lack of second-rank polymorphism.
For instance,

      let y = m 2. * m 3.

works but

     let x = m 2. in
     let y = x * x

doe not. Even worse

let () =
     let x = m 1. in
     let y = m 2. in
     let w = x * y in
     ()

works but

let () =
     let x = m 1. in
     let y = m 2. in
     let w = x * y in
     let z = x + y in
     ()

triggers a compilation error.
And unfortunately, I am not aware of any way to avoid these quirky 
behaviors.

Regards,
octachron.

Le 10/16/14 18:37, Shayne Fletcher a écrit :
> Dear OCamlers,
>
> In 1994, Barton and Nackman in their book 'Scientific Engineering in
> C++' [1] demonstrated how one could encode the rules of Dimensional
> Analysis [2] into the C++ type system enabling compile-time checking
> (no runtime-cost) of the plausibility (at least up to the dimensional
> correctness) of computations.
>
> In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3]
> showed the Barton Nackman technique to be elegantly implementable
> using compile time type sequences encoding integer constants. At the
> end of this post, I provide a complete listing of their example
> program [4].
>
> The key properties of the system (as I see it) are:
>   - Encoding of integers as types;
>   - Compile time manipulation of sequences of these integer encodings
>     to deduce/produce new derived types.
>
> Now, it is not immediately obvious to me how to approach this problem
> in OCaml. It irks me some that I can't immediately produce a yet more
> elegant OCaml program for this problem and leaves me feeling like C++
> has "got something over on us" here ;)
>
> My question therefore is: Does anyone have suggestions/pointers
> on how to approach automatic dimensional analysis via the OCaml type
> system?
>
> Best,
>
> -- 
> Shayne Fletcher
>
> [1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++:
>     an Introduction with Advanced Techniques and Examples. Reading,
>     MA: Addison Wesley. ISBN 0-201-53393-6. 1994.
>
> [2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis
>
> [3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming:
>     Concepts, Tools, and Techniques from Boost and Beyond (C++ in
>     Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004.
>
> [4] Code listing:
>
>     //"c:/program files (x86)/Microsoft Visual Studio 
> 10.0/vc/vcvarsall.bat" x64
>     //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp
>     #include <boost/mpl/vector_c.hpp>
>     #include <boost/mpl/transform.hpp>
>     #include <boost/mpl/placeholders.hpp>
>     #include <boost/mpl/equal.hpp>
>     #include <boost/mpl/plus.hpp>
>     #include <boost/mpl/minus.hpp>
>     #include <boost/static_assert.hpp>
>     typedef boost::mpl::vector_c<int,1,0,0,0,0,0,0> mass;
>     typedef boost::mpl::vector_c<int,0,1,0,0,0,0,0> length;
>     typedef boost::mpl::vector_c<int,0,0,1,0,0,0,0> time;
>     typedef boost::mpl::vector_c<int,0,0,0,1,0,0,0> charge;
>     typedef boost::mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,1> angle;
>     typedef boost::mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;   // l/t
>     typedef boost::mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // 
> l/(t2)
>     typedef boost::mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;   // ml/t
>     typedef boost::mpl::vector_c<int,1,1,-2,0,0,0,0> force;    // ml/(t2)
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
>     template <class T, class Dimensions>
>     class quantity
>     {
>     public:
>       explicit quantity (T val)
>         : val (val)
>       {}
>       template <class OtherDimensions>
>       quantity (quantity<T, OtherDimensions> const& other)
>         : val (other.value ()) {
>         BOOST_MPL_ASSERT( (boost::mpl::equal<Dimensions, 
> OtherDimensions>));
>       }
>       T value () const { return val; }
>     private:
>       T val;
>     };
>     template <class T, class D>
>     quantity<T, D>
>     operator + (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () + y.value ());
>     }
>     template <class T, class D>
>     quantity<T, D>
>     operator - (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () - y.value ());
>     }
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type
>     >
>     operator* (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>       return quantity<T, D> (x.value () * y.value ());
>     }
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type
>     >
>     operator/ (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>       return quantity<T, D> (x.value () / y.value ());
>     }
>     // -- test
>     #include <iostream>
>   #include <limits>
>   #include <cassert>
>     int main ()
>     {
>       quantity<float, mass> m (5.0f);
>       quantity<float, acceleration> a(9.8f);
>       quantity<float, force> f = m * a;
>       quantity<float, mass> m2 = f / a;
>       assert ((std::abs ((m2 - m).value ())) <= 
> std::numeric_limits<double>::epsilon ());
>       return 0;
>     }
>


[-- Attachment #2: Type: text/html, Size: 26392 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
  2014-10-16 17:21 ` Octachron
@ 2014-10-16 17:35 ` Mario Alvarez Picallo
  2014-10-17  5:58   ` Octachron
  2014-11-10 18:14   ` Shayne Fletcher
  2014-10-16 18:10 ` Thomas Gazagnaire
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 9+ messages in thread
From: Mario Alvarez Picallo @ 2014-10-16 17:35 UTC (permalink / raw)
  To: Shayne Fletcher; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 6383 bytes --]

Hello Shayne,

I was at first convinced that this could not be done, but you can in fact
encode it (in a verbose way) with phantom types,
using a smart typelevel representation of integers (
http://www.kb.ecei.tohoku.ac.jp/ml2008/slides/lindley.pdf).

I've written a small proof of concept that seems to work just fine (but, of
course, there may be errors), that you can find
here: https://gist.github.com/m-alvarez/b1e42b7b42cbeed7d1f0

It seems to be solid enough to pass the tests that Octachron tried, but
there probably are some other corner cases for which
it breaks down. Otherwise, it would be interesting to coalesce both
representations, using Octachron's idea of row types instead
of tuples to have extensible dimensional analysis, where each part of the
program can introduce its own dimensions.

Regards,
Mario A.

On Thu, Oct 16, 2014 at 6:37 PM, Shayne Fletcher <
shayne.fletcher.50@gmail.com> wrote:

> Dear OCamlers,
>
> In 1994, Barton and Nackman in their book 'Scientific Engineering in
> C++' [1] demonstrated how one could encode the rules of Dimensional
> Analysis [2] into the C++ type system enabling compile-time checking
> (no runtime-cost) of the plausibility (at least up to the dimensional
> correctness) of computations.
>
> In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3]
> showed the Barton Nackman technique to be elegantly implementable
> using compile time type sequences encoding integer constants. At the
> end of this post, I provide a complete listing of their example
> program [4].
>
> The key properties of the system (as I see it) are:
>   - Encoding of integers as types;
>   - Compile time manipulation of sequences of these integer encodings
>     to deduce/produce new derived types.
>
> Now, it is not immediately obvious to me how to approach this problem
> in OCaml. It irks me some that I can't immediately produce a yet more
> elegant OCaml program for this problem and leaves me feeling like C++
> has "got something over on us" here ;)
>
> My question therefore is: Does anyone have suggestions/pointers
> on how to approach automatic dimensional analysis via the OCaml type
> system?
>
> Best,
>
> --
> Shayne Fletcher
>
> [1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++:
>     an Introduction with Advanced Techniques and Examples. Reading,
>     MA: Addison Wesley. ISBN 0-201-53393-6. 1994.
>
> [2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis
>
> [3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming:
>     Concepts, Tools, and Techniques from Boost and Beyond (C++ in
>     Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004.
>
> [4] Code listing:
>
>     //"c:/program files (x86)/Microsoft Visual Studio
> 10.0/vc/vcvarsall.bat" x64
>     //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp
>
>     #include <boost/mpl/vector_c.hpp>
>     #include <boost/mpl/transform.hpp>
>     #include <boost/mpl/placeholders.hpp>
>     #include <boost/mpl/equal.hpp>
>     #include <boost/mpl/plus.hpp>
>     #include <boost/mpl/minus.hpp>
>     #include <boost/static_assert.hpp>
>
>     typedef boost::mpl::vector_c<int,1,0,0,0,0,0,0> mass;
>     typedef boost::mpl::vector_c<int,0,1,0,0,0,0,0> length;
>     typedef boost::mpl::vector_c<int,0,0,1,0,0,0,0> time;
>     typedef boost::mpl::vector_c<int,0,0,0,1,0,0,0> charge;
>     typedef boost::mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,1> angle;
>     typedef boost::mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;     // l/t
>     typedef boost::mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; //
> l/(t2)
>     typedef boost::mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;     // ml/t
>     typedef boost::mpl::vector_c<int,1,1,-2,0,0,0,0> force;        //
> ml/(t2)
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
>
>     template <class T, class Dimensions>
>     class quantity
>     {
>     public:
>       explicit quantity (T val)
>         : val (val)
>       {}
>       template <class OtherDimensions>
>       quantity (quantity<T, OtherDimensions> const& other)
>         : val (other.value ()) {
>         BOOST_MPL_ASSERT( (boost::mpl::equal<Dimensions,
> OtherDimensions>));
>       }
>       T value () const { return val; }
>     private:
>       T val;
>     };
>
>     template <class T, class D>
>     quantity<T, D>
>     operator + (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () + y.value ());
>     }
>
>     template <class T, class D>
>     quantity<T, D>
>     operator - (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () - y.value ());
>     }
>
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type
>     >
>     operator* (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>
>       return quantity<T, D> (x.value () * y.value ());
>     }
>
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type
>     >
>     operator/ (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>
>       return quantity<T, D> (x.value () / y.value ());
>     }
>
>     // -- test
>
>     #include <iostream>
>     #include <limits>
>     #include <cassert>
>
>     int main ()
>     {
>       quantity<float, mass> m (5.0f);
>       quantity<float, acceleration> a(9.8f);
>       quantity<float, force> f = m * a;
>       quantity<float, mass> m2 = f / a;
>
>       assert ((std::abs ((m2 - m).value ())) <=
> std::numeric_limits<double>::epsilon ());
>
>       return 0;
>     }
>
>

[-- Attachment #2: Type: text/html, Size: 18488 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
  2014-10-16 17:21 ` Octachron
  2014-10-16 17:35 ` Mario Alvarez Picallo
@ 2014-10-16 18:10 ` Thomas Gazagnaire
  2014-10-17 10:22   ` David MENTRE
  2014-10-16 19:36 ` Shayne Fletcher
  2014-10-17  6:50 ` Roberto Di Cosmo
  4 siblings, 1 reply; 9+ messages in thread
From: Thomas Gazagnaire @ 2014-10-16 18:10 UTC (permalink / raw)
  To: Shayne Fletcher; +Cc: caml-list@inria.fr users

[-- Attachment #1: Type: text/plain, Size: 5851 bytes --]

You might be interested by http://akabe.github.io/slap/

Thomas

On 16 Oct 2014, at 17:37, Shayne Fletcher <shayne.fletcher.50@gmail.com> wrote:

> Dear OCamlers,
> 
> In 1994, Barton and Nackman in their book 'Scientific Engineering in
> C++' [1] demonstrated how one could encode the rules of Dimensional
> Analysis [2] into the C++ type system enabling compile-time checking
> (no runtime-cost) of the plausibility (at least up to the dimensional
> correctness) of computations.
> 
> In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3]
> showed the Barton Nackman technique to be elegantly implementable
> using compile time type sequences encoding integer constants. At the
> end of this post, I provide a complete listing of their example
> program [4].
> 
> The key properties of the system (as I see it) are:
>   - Encoding of integers as types; 
>   - Compile time manipulation of sequences of these integer encodings
>     to deduce/produce new derived types.
> 
> Now, it is not immediately obvious to me how to approach this problem
> in OCaml. It irks me some that I can't immediately produce a yet more
> elegant OCaml program for this problem and leaves me feeling like C++
> has "got something over on us" here ;)
> 
> My question therefore is: Does anyone have suggestions/pointers
> on how to approach automatic dimensional analysis via the OCaml type
> system? 
> 
> Best,
> 
> -- 
> Shayne Fletcher
> 
> [1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++:
>     an Introduction with Advanced Techniques and Examples. Reading,
>     MA: Addison Wesley. ISBN 0-201-53393-6. 1994.
> 
> [2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis
> 
> [3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming:
>     Concepts, Tools, and Techniques from Boost and Beyond (C++ in
>     Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004.
> 
> [4] Code listing:
> 
>     //"c:/program files (x86)/Microsoft Visual Studio 10.0/vc/vcvarsall.bat" x64
>     //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp
>     
>     #include <boost/mpl/vector_c.hpp>
>     #include <boost/mpl/transform.hpp>
>     #include <boost/mpl/placeholders.hpp>
>     #include <boost/mpl/equal.hpp>
>     #include <boost/mpl/plus.hpp>
>     #include <boost/mpl/minus.hpp>
>     #include <boost/static_assert.hpp>
>     
>     typedef boost::mpl::vector_c<int,1,0,0,0,0,0,0> mass;
>     typedef boost::mpl::vector_c<int,0,1,0,0,0,0,0> length;
>     typedef boost::mpl::vector_c<int,0,0,1,0,0,0,0> time;
>     typedef boost::mpl::vector_c<int,0,0,0,1,0,0,0> charge;
>     typedef boost::mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,1> angle;
>     typedef boost::mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;     // l/t
>     typedef boost::mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // l/(t2)
>     typedef boost::mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;     // ml/t
>     typedef boost::mpl::vector_c<int,1,1,-2,0,0,0,0> force;        // ml/(t2)
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
>     
>     template <class T, class Dimensions>
>     class quantity
>     {
>     public:
>       explicit quantity (T val) 
>         : val (val)
>       {}
>       template <class OtherDimensions>
>       quantity (quantity<T, OtherDimensions> const& other)
>         : val (other.value ()) {
>         BOOST_MPL_ASSERT( (boost::mpl::equal<Dimensions, OtherDimensions>));
>       }
>       T value () const { return val; }
>     private:
>       T val;
>     };
>     
>     template <class T, class D>
>     quantity<T, D>
>     operator + (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () + y.value ());
>     }
>     
>     template <class T, class D>
>     quantity<T, D>
>     operator - (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () - y.value ());
>     }
>     
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type 
>     >
>     operator* (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>     
>       return quantity<T, D> (x.value () * y.value ());
>     }
>     
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type 
>     >
>     operator/ (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>     
>       return quantity<T, D> (x.value () / y.value ());
>     }
>     
>     // -- test
>     
>     #include <iostream>
>     #include <limits>
>     #include <cassert>
>     
>     int main ()
>     {
>       quantity<float, mass> m (5.0f);
>       quantity<float, acceleration> a(9.8f);
>       quantity<float, force> f = m * a;
>       quantity<float, mass> m2 = f / a;
>     
>       assert ((std::abs ((m2 - m).value ())) <= std::numeric_limits<double>::epsilon ());
>     
>       return 0;
>     }
> 


[-- Attachment #2: Type: text/html, Size: 20288 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
                   ` (2 preceding siblings ...)
  2014-10-16 18:10 ` Thomas Gazagnaire
@ 2014-10-16 19:36 ` Shayne Fletcher
  2014-10-17  6:50 ` Roberto Di Cosmo
  4 siblings, 0 replies; 9+ messages in thread
From: Shayne Fletcher @ 2014-10-16 19:36 UTC (permalink / raw)
  To: caml-list@inria.fr users

[-- Attachment #1: Type: text/plain, Size: 350 bytes --]

On Thu, Oct 16, 2014 at 12:37 PM, Shayne Fletcher <
shayne.fletcher.50@gmail.com> wrote:

> My question therefore is: Does anyone have suggestions/pointers
> on how to approach automatic dimensional analysis via the OCaml type
> system?
>

​Thanks Octachron, Mario, Thomas... Great help. I've got some study to do!

-- 
Shayne Fletcher

[-- Attachment #2: Type: text/html, Size: 1171 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 17:35 ` Mario Alvarez Picallo
@ 2014-10-17  5:58   ` Octachron
  2014-11-10 18:14   ` Shayne Fletcher
  1 sibling, 0 replies; 9+ messages in thread
From: Octachron @ 2014-10-17  5:58 UTC (permalink / raw)
  To: caml-list

Le 10/16/14 19:35, Mario Alvarez Picallo wrote:
> Hello Shayne,
>
> I was at first convinced that this could not be done, but you can in 
> fact encode it (in a verbose way) with phantom types,
> using a smart typelevel representation of integers 
> (http://www.kb.ecei.tohoku.ac.jp/ml2008/slides/lindley.pdf).
>
> I've written a small proof of concept that seems to work just fine 
> (but, of course, there may be errors), that you can find
> here: https://gist.github.com/m-alvarez/b1e42b7b42cbeed7d1f0
>
> It seems to be solid enough to pass the tests that Octachron tried, 
> but there probably are some other corner cases for which
> it breaks down. Otherwise, it would be interesting to coalesce both 
> representations, using Octachron's idea of row types instead
> of tuples to have extensible dimensional analysis, where each part of 
> the program can introduce its own dimensions.
>
> Regards,
> Mario A.
>

I forget to add variance annotation in my test so my examples broke down 
due to the presence of monomorphic types. With the right implementation 
(i.e. Mario's),
problems appear within functions. For instance,

let f x = x* x

works only for adimensional variable (i.e f : ('a*'a) t -> ('a*'a) t ) 
which is maybe not surprising.
However, the same thing  also happens to

let f x y = (x+y)*x*y .

because the type of x and y are unified during the addition "x+y".

Regards,
Octachron.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
                   ` (3 preceding siblings ...)
  2014-10-16 19:36 ` Shayne Fletcher
@ 2014-10-17  6:50 ` Roberto Di Cosmo
  4 siblings, 0 replies; 9+ messages in thread
From: Roberto Di Cosmo @ 2014-10-17  6:50 UTC (permalink / raw)
  To: Shayne Fletcher; +Cc: caml-list@inria.fr users

Dear Shayne,
   you might have a look at the thread answering a similar question
I asked last june on the list, here:

https://sympa.inria.fr/sympa/arc/caml-list/2014-06/msg00066.html

Notice that the very first viable experiment of a variant of CamlLight
with full dimension types (non encodings) was announced by Bruno Blanchet back in 1995
http://caml.inria.fr/pub/ml-archives/caml-list/1995/12/2c6fa7b3b2b429cf39f10b60d2230850.fr.html

--
Roberto

On Thu, Oct 16, 2014 at 12:37:19PM -0400, Shayne Fletcher wrote:
> Dear OCamlers,
> 
> In 1994, Barton and Nackman in their book 'Scientific Engineering in
> C++' [1] demonstrated how one could encode the rules of Dimensional
> Analysis [2] into the C++ type system enabling compile-time checking
> (no runtime-cost) of the plausibility (at least up to the dimensional
> correctness) of computations.
> 
> In 2004, Abrahams & Gurtovy in 'C++ Template Metaprogramming' [3]
> showed the Barton Nackman technique to be elegantly implementable
> using compile time type sequences encoding integer constants. At the
> end of this post, I provide a complete listing of their example
> program [4].
> 
> The key properties of the system (as I see it) are:
>   - Encoding of integers as types; 
>   - Compile time manipulation of sequences of these integer encodings
>     to deduce/produce new derived types.
> 
> Now, it is not immediately obvious to me how to approach this problem
> in OCaml. It irks me some that I can't immediately produce a yet more
> elegant OCaml program for this problem and leaves me feeling like C++
> has "got something over on us" here ;)
> 
> My question therefore is: Does anyone have suggestions/pointers
> on how to approach automatic dimensional analysis via the OCaml type
> system? 
> 
> Best,
> 
> -- 
> Shayne Fletcher
> 
> [1] John J. Barton and Lee R. Nackman. Scientific and Engineering C++:
>     an Introduction with Advanced Techniques and Examples. Reading,
>     MA: Addison Wesley. ISBN 0-201-53393-6. 1994.
> 
> [2] Wikipedia http://en.wikipedia.org/wiki/Dimensional_analysis
> 
> [3] David Abrahams and Aleksey Gurtovy C++ Template Metaprogramming:
>     Concepts, Tools, and Techniques from Boost and Beyond (C++ in
>     Depth Series), Addison-Wesley Professional. ISBN:0321227255. 2004.
> 
> [4] Code listing:
> 
>     //"c:/program files (x86)/Microsoft Visual Studio 10.0/vc/vcvarsall.bat"
> x64
>     //cl /Fedimension.exe /EHsc /I d:/boost_1_55_0 dimension.cpp
>     
>     #include <boost/mpl/vector_c.hpp>
>     #include <boost/mpl/transform.hpp>
>     #include <boost/mpl/placeholders.hpp>
>     #include <boost/mpl/equal.hpp>
>     #include <boost/mpl/plus.hpp>
>     #include <boost/mpl/minus.hpp>
>     #include <boost/static_assert.hpp>
>     
>     typedef boost::mpl::vector_c<int,1,0,0,0,0,0,0> mass;
>     typedef boost::mpl::vector_c<int,0,1,0,0,0,0,0> length;
>     typedef boost::mpl::vector_c<int,0,0,1,0,0,0,0> time;
>     typedef boost::mpl::vector_c<int,0,0,0,1,0,0,0> charge;
>     typedef boost::mpl::vector_c<int,0,0,0,0,1,0,0> temperature;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,1,0> intensity;
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,1> angle;
>     typedef boost::mpl::vector_c<int,0,1,-1,0,0,0,0> velocity;     // l/t
>     typedef boost::mpl::vector_c<int,0,1,-2,0,0,0,0> acceleration; // l/(t2)
>     typedef boost::mpl::vector_c<int,1,1,-1,0,0,0,0> momentum;     // ml/t
>     typedef boost::mpl::vector_c<int,1,1,-2,0,0,0,0> force;        // ml/(t2)
>     typedef boost::mpl::vector_c<int,0,0,0,0,0,0,0> scalar;
>     
>     template <class T, class Dimensions>
>     class quantity
>     {
>     public:
>       explicit quantity (T val) 
>         : val (val)
>       {}
>       template <class OtherDimensions>
>       quantity (quantity<T, OtherDimensions> const& other)
>         : val (other.value ()) {
>         BOOST_MPL_ASSERT( (boost::mpl::equal<Dimensions, OtherDimensions>));
>       }
>       T value () const { return val; }
>     private:
>       T val;
>     };
>     
>     template <class T, class D>
>     quantity<T, D>
>     operator + (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () + y.value ());
>     }
>     
>     template <class T, class D>
>     quantity<T, D>
>     operator - (quantity<T, D> x, quantity<T, D> y )
>     {
>       return quantity<T, D>(x.value () - y.value ());
>     }
>     
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type 
>     >
>     operator* (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::plus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>     
>       return quantity<T, D> (x.value () * y.value ());
>     }
>     
>     template <class T, class D1, class D2>
>     quantity <
>       T
>     , typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                 , boost::mpl::placeholders::_2> >::type 
>     >
>     operator/ (quantity<T, D1> x, quantity <T, D2> y)
>     {
>       typedef typename boost::mpl::transform<
>         D1, D2, boost::mpl::minus<
>                   boost::mpl::placeholders::_1
>                   , boost::mpl::placeholders::_2> >::type D;
>     
>       return quantity<T, D> (x.value () / y.value ());
>     }
>     
>     // -- test
>     
>     #include <iostream>
>     #include <limits>
>     #include <cassert>
>     
>     int main ()
>     {
>       quantity<float, mass> m (5.0f);
>       quantity<float, acceleration> a(9.8f);
>       quantity<float, force> f = m * a;
>       quantity<float, mass> m2 = f / a;
>     
>       assert ((std::abs ((m2 - m).value ())) <= std::numeric_limits
> <double>::epsilon ());
>     
>       return 0;
>     }
> 

-- 
Roberto Di Cosmo
 
------------------------------------------------------------------
Professeur               En delegation a l'INRIA
PPS                      E-mail: roberto@dicosmo.org
Universite Paris Diderot WWW  : http://www.dicosmo.org
Case 7014                Tel  : ++33-(0)1-57 27 92 20
5, Rue Thomas Mann       
F-75205 Paris Cedex 13   Identica: http://identi.ca/rdicosmo
FRANCE.                  Twitter: http://twitter.com/rdicosmo
------------------------------------------------------------------
Attachments:
MIME accepted, Word deprecated
      http://www.gnu.org/philosophy/no-word-attachments.html
------------------------------------------------------------------
Office location:
 
Bureau 3020 (3rd floor)
Batiment Sophie Germain
Avenue de France
Metro Bibliotheque Francois Mitterrand, ligne 14/RER C
-----------------------------------------------------------------
GPG fingerprint 2931 20CE 3A5A 5390 98EC 8BFC FCCA C3BE 39CB 12D3                        

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 18:10 ` Thomas Gazagnaire
@ 2014-10-17 10:22   ` David MENTRE
  0 siblings, 0 replies; 9+ messages in thread
From: David MENTRE @ 2014-10-17 10:22 UTC (permalink / raw)
  To: caml-list

Hello Thomas,

Le 16/10/2014 20:10, Thomas Gazagnaire a écrit :
> You might be interested by http://akabe.github.io/slap/

As far as I understand it, slap checks dimensions with the meaning 
*size* (of matrices, vectors). But slap does not help for checking 
*physical* dimensions (meters, seconds, m*s^-2, ...).

Best regards,
david


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] Dimensional Analysis question
  2014-10-16 17:35 ` Mario Alvarez Picallo
  2014-10-17  5:58   ` Octachron
@ 2014-11-10 18:14   ` Shayne Fletcher
  1 sibling, 0 replies; 9+ messages in thread
From: Shayne Fletcher @ 2014-11-10 18:14 UTC (permalink / raw)
  To: Mario Alvarez Picallo; +Cc: caml-list@inria.fr users

[-- Attachment #1: Type: text/plain, Size: 891 bytes --]

On Thu, Oct 16, 2014 at 1:35 PM, Mario Alvarez Picallo <
mario.alvarez739@gmail.com> wrote:

> I've written a small proof of concept that seems to work just fine (but,
> of course, there may be errors), that you can find
> here: https://gist.github.com/m-alvarez/b1e42b7b42cbeed7d1f0
>

​Mario, thanks for the links and this, this is truly a beautiful little
program.


>
>
> It seems to be solid enough to pass the tests that Octachron tried, but
> there probably are some other corner cases for which
> it breaks down. Otherwise, it would be interesting to coalesce both
> representations, using Octachron's idea of row types instead
> of tuples to have extensible dimensional analysis, where each part of the
> program can introduce its own dimensions.


​Mario, Octachron, thanks again. Really helped me out. Mind blowing stuff!
:)​

-- 
Shayne Fletcher

[-- Attachment #2: Type: text/html, Size: 1647 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-11-10 18:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-16 16:37 [Caml-list] Dimensional Analysis question Shayne Fletcher
2014-10-16 17:21 ` Octachron
2014-10-16 17:35 ` Mario Alvarez Picallo
2014-10-17  5:58   ` Octachron
2014-11-10 18:14   ` Shayne Fletcher
2014-10-16 18:10 ` Thomas Gazagnaire
2014-10-17 10:22   ` David MENTRE
2014-10-16 19:36 ` Shayne Fletcher
2014-10-17  6:50 ` Roberto Di Cosmo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).