Topic: Deterministic functions


Author: F.Zwarts@KVI.nl ("Fred Zwarts")
Date: Wed, 28 Mar 2007 14:39:10 GMT
Raw View
"Pedro Lamar=E3o" <pedro.lamarao@gmail.com> wrote in message news:1174671=
306.063596.324290@l77g2000hsb.googlegroups.com...
> On 23 mar, 14:57, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
>=20
>> Exactly. The idea of a deterministic function was that it depends only
>> on its parameters. Since the parameters of size () are always the same
>> (void), the result must be always the same. However, the result of
>> size () is not always the same, it varies with the size of the contain=
er.
>=20
> A "deterministic" keyword would not be much more useful than the
> current "inline" keyword.

Except that for inline functions the compiler has access to the body of t=
he function.
For "deterministic" functions, the body may be in another compilation uni=
t.

> The only thing the standard can say about it is "this is a hint to a
> possible optimization the user would like".
> But specifying a deterministic keyword does not magically produce
> compilers capable to prove that any function has this deterministic
> property.
>=20
> If we make the optimization required on the keyword we would also need
> to require a diagnostic if the user broke the rules;  to actually
> produce such diagnostics the compiler would need to prove the function
> is _not_ actually deterministic.

I agree with this. But I don't know how difficult it is to check it.
=20
> (Else, we mark rules breakage as undefined behaviour. Argh!)
>=20
> A compiler that actually is capable of proving a function has this
> deterministic property don't need a new keyword to make optimizations
> based on this knowledge. It is probably already doing it.

This is true only if the body of the function is in the same compilation =
unit.
But in particular for complex expensive function, one probably would plac=
e
them in a separate compilation unit and this is exactly a case where a
"deterministic" keyword would help significantly.

> I don't think we need new "hint to optimization" keywords.

No, but maybe the checks are not that difficult, so that it is not only a=
 hint.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: F.Zwarts@KVI.nl ("Fred Zwarts")
Date: Wed, 28 Mar 2007 16:36:04 GMT
Raw View
"jam" <farid.mehrabi@gmail.com> wrote in message news:1175006106.636130.238280@b75g2000hsg.googlegroups.com...
> On Mar 23, 9:57 pm, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
>> <jose.di...@gmail.com> wrote in messagenews:1174505483.911510.39770@y66g2000hsf.googlegroups.com...
>> > On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
>> >> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
>> >> but somehow suppressed by other things. The concept of pure functions
>> >> not only enables additional compiler optimizations, but also adds to
>> >> the static safety of the code (like keyword const does). I also found
>> >> it useful in refactoring long functions that may (or not) rely on
>> >> static data.
>>
>> >> In the Container example, I think the 'deterministic' implies 'const',
>> >> (it is even stronger). It would suffice to write:
>>
>> >> class Container {
>> >>     public:
>> >>       int size() deterministic; // is const because it is
>> >> deterministic
>> >>       Item& getAt(index i) deterministic; // const again
>> >>       void add(Item item);
>> >>   };
>>
>> > sorry, but I can't buy that in the container example
>>
>> > see:
>>
>> > while( somecondition() ) {
>> >  somefuncion( container.size() );        // parameter will change
>> > everytime. how deterministic will help here?
>> >  container.add( something );
>> > }
>>
>> Exactly. The idea of a deterministic function was that it depends only
>> on its parameters. Since the parameters of size () are always the same
>> (void), the result must be always the same. However, the result of
>> size () is not always the same, it varies with the size of the container.
>>
>> If size () would be deterministic one could also argue that any function that
>> depends on a global variable (or on any other property of the environment)
>> could be deterministic. This would limit the optimization of deterministic
>> functions a lot, because the compiler would no longer be able to know whether
>> or not the environment has changed, so it must create a function call again to be
>> sure to get the correct result.
>> In this example the code for the add () function and the code for the size () function
>> could be invisible for the compiler (just as the code of any member function of the
>> container). The compiler does not know on which other object members the result
>> of size () depends. So the result of size ()  may change after a call to any other member
>> function or operator. So, there remains little opportunities for the compiler to optimize
>> calls to size ().
>> This means that other, true deterministic function, have also little opportunities for optimization.
>>
>> ---
>> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
>> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
>> [              --- Please see the FAQ before posting. ---               ]
>> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]- Hide quoted text -
>>
>> - Show quoted text -
>
> looks like we are forgetting that instance member methods get a hidden
> 'this' parameter too.So if the memeber functions is declared as
> pure(deterministic ...) then it will act as a pure function if and
> only if all the parameters including the hidden 'this'  parameter are
> evaluated at compile time.

In my opinion, the "deterministic" keyword should be reserved to functions
that do not really use the 'this' parameter, i.e. to static functions and
functions that are not part of a class definition.
You seem to have anotehr idea:

> Therefore we have to extend the keyword to
> cover objects too:
>
> struct A{
>            A() deterministic;
>            void f() deterministic;
> };
>
> deterministic A a;
> a.f();//run at compile time
> A b;
> b.f();//evaluate at run time
>
> IMHO deteministic is a synonym for literal but literal need not be
> const.Take __LINE__ predefined macro for example; it is evaluated at
> compile time but has different values in different places which means
> it is a none-const literal(deterministic) value.

Could you describe what it means when an object is deterministic?
Is the object a const?
Is it disallowed to call non-deterministic functions of a deterministic object?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "=?iso-8859-1?q?Pedro_Lamar=E3o?=" <pedro.lamarao@gmail.com>
Date: Wed, 28 Mar 2007 12:31:21 CST
Raw View
On 28 mar, 11:39, F.Zwa...@KVI.nl ("Fred Zwarts") wrote:

> > A compiler that actually is capable of proving a function has this
> > deterministic property don't need a new keyword to make optimizations
> > based on this knowledge. It is probably already doing it.
>
> This is true only if the body of the function is in the same compilation unit.
> But in particular for complex expensive function, one probably would place
> them in a separate compilation unit and this is exactly a case where a
> "deterministic" keyword would help significantly.

The fact that a function declaration is annotated with this
deterministic keyword does not prove calling the function produces no
side effects.

The analogy between "deterministic" and "inline" as "hints to
optimization" is dangerous: inlining a function call does not change
the semantics of a program; caching the results of a function call can
change the semantics of a program depending on the function's side
effects.

No compiler can cache the results for such a function, even in the
presence of a deterministic annotation, without actual proof that the
function is truly deterministic.

A compiler that is capable, somehow, of proving a function is truly
deterministic does not need a deterministic annotation to optimize
calls to it.

A compiler that is not capable of this proof would not be allowed to
optimize calls to this function even in the presence of the
deterministic annotation.

If the standard allowed such compilers to optimize calls to this
function even without actual proof the function is deterministic it
would also need to state that calling a function that is both:

  a) annotated as deterministic
  b) has side effects

invokes undefined behaviour.

As far as I can see we have only two choices to introduce this
deterministic concept explicitly in the language.

1) We state the rules for a deterministic function and require that
compilers check if functions declared to be deterministic actually
follow the rules; if they don't, the program is ill formed and
diagnostic is required.

2) We state the allowed optimizations that can be applied to functions
that are declared as deterministic based on certain assumptions
implied by the declaration and state that calling a function whose
implementation violates these assumptions invokes undefined behaviour.

--
 Pedro Lamar   o


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: bop@gmb.dk ("Bo Persson")
Date: Wed, 28 Mar 2007 18:44:56 GMT
Raw View
"Fred Zwarts" wrote:
: "Pedro Lamar=E3o" <pedro.lamarao@gmail.com> wrote in message
: news:1174671306.063596.324290@l77g2000hsb.googlegroups.com...
:: On 23 mar, 14:57, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
::
::: Exactly. The idea of a deterministic function was that it depends
::: only on its parameters. Since the parameters of size () are always
::: the same (void), the result must be always the same. However, the
::: result of
::: size () is not always the same, it varies with the size of the
::: container.
::
:: A "deterministic" keyword would not be much more useful than the
:: current "inline" keyword.
:
: Except that for inline functions the compiler has access to the body
: of the function.
: For "deterministic" functions, the body may be in another compilation
: unit.

But right now compilers are inlining functions across compilation units.=20
There is no need to see the function body until link-time, to do that.

That's why introducing another keyword to solve a similar problem seems l=
ike=20
not a good idea.


Bo Persson



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jam" <farid.mehrabi@gmail.com>
Date: Thu, 29 Mar 2007 10:14:27 CST
Raw View
On Mar 28, 8:36 pm, F.Zwa...@KVI.nl ("Fred Zwarts") wrote:
> "jam" <farid.mehr...@gmail.com> wrote in messagenews:1175006106.636130.238280@b75g2000hsg.googlegroups.com...
> > On Mar 23, 9:57 pm, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
> >> <jose.di...@gmail.com> wrote in messagenews:1174505483.911510.39770@y66g2000hsf.googlegroups.com...
> >> > On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
> >> >> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> >> >> but somehow suppressed by other things. The concept of pure functions
> >> >> not only enables additional compiler optimizations, but also adds to
> >> >> the static safety of the code (like keyword const does). I also found
> >> >> it useful in refactoring long functions that may (or not) rely on
> >> >> static data.
>
> >> >> In the Container example, I think the 'deterministic' implies 'const',
> >> >> (it is even stronger). It would suffice to write:
>
> >> >> class Container {
> >> >>     public:
> >> >>       int size() deterministic; // is const because it is
> >> >> deterministic
> >> >>       Item& getAt(index i) deterministic; // const again
> >> >>       void add(Item item);
> >> >>   };
>
> >> > sorry, but I can't buy that in the container example
>
> >> > see:
>
> >> > while( somecondition() ) {
> >> >  somefuncion( container.size() );        // parameter will change
> >> > everytime. how deterministic will help here?
> >> >  container.add( something );
> >> > }
>
> >> Exactly. The idea of a deterministic function was that it depends only
> >> on its parameters. Since the parameters of size () are always the same
> >> (void), the result must be always the same. However, the result of
> >> size () is not always the same, it varies with the size of the container.
>
> >> If size () would be deterministic one could also argue that any function that
> >> depends on a global variable (or on any other property of the environment)
> >> could be deterministic. This would limit the optimization of deterministic
> >> functions a lot, because the compiler would no longer be able to know whether
> >> or not the environment has changed, so it must create a function call again to be
> >> sure to get the correct result.
> >> In this example the code for the add () function and the code for the size () function
> >> could be invisible for the compiler (just as the code of any member function of the
> >> container). The compiler does not know on which other object members the result
> >> of size () depends. So the result of size ()  may change after a call to any other member
> >> function or operator. So, there remains little opportunities for the compiler to optimize
> >> calls to size ().
> >> This means that other, true deterministic function, have also little opportunities for optimization.
>
> >> ---
> >> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> >> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> >> [              --- Please see the FAQ before posting. ---               ]
> >> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                    ]- Hide quoted text -
>
> >> - Show quoted text -
>
> > looks like we are forgetting that instance member methods get a hidden
> > 'this' parameter too.So if the memeber functions is declared as
> > pure(deterministic ...) then it will act as a pure function if and
> > only if all the parameters including the hidden 'this'  parameter are
> > evaluated at compile time.
>
> In my opinion, the "deterministic" keyword should be reserved to functions
> that do not really use the 'this' parameter, i.e. to static functions and
> functions that are not part of a class definition.
> You seem to have anotehr idea:
>
>
>
>
>
> > Therefore we have to extend the keyword to
> > cover objects too:
>
> > struct A{
> >            A() deterministic;
> >            void f() deterministic;
> > };
>
> > deterministic A a;
> > a.f();//run at compile time
> > A b;
> > b.f();//evaluate at run time
>
> > IMHO deteministic is a synonym for literal but literal need not be
> > const.Take __LINE__ predefined macro for example; it is evaluated at
> > compile time but has different values in different places which means
> > it is a none-const literal(deterministic) value.
>
> Could you describe what it means when an object is deterministic?
> Is the object a const?
> Is it disallowed to call non-deterministic functions of a deterministic object?
>
You have touched the point. It isdisallowed to call non-deterministic
functions of a deterministic object.But deterministc is different from
const.It specifies an object or function that is processed and
initialized at compile time and accessed as a const object at run
time.Whereas a const object is the data that is not to be changed
after initialization.If you combine both deterministic and const
specifiers for an object or function then it means that even at
compile time the object is not to be changed after construction:

struct A{
         A()detrminsitic;
         void f()deterministic;
         void g();
};

deteministic const A a1;//ok: a compile time const A
deteministic A a2;//ok:a compile time processed A
A a3;//ok:a runtime processed A

a1.f();//error :f is not specified as deterministic const
a2.f();//ok: f is specified as deterministic
a2.g();//error: g is not specified as deterministic
a3.f();//ok: f is processed at runtime though it is specified as
deterministic
a3.g();//ok: just as before g is processed at runtime




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: nagle@animats.com (John Nagle)
Date: Sat, 24 Mar 2007 14:03:23 GMT
Raw View
Pedro Lamar=E3o wrote:
> On 23 mar, 14:57, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
>=20
>=20
>>Exactly. The idea of a deterministic function was that it depends only
>>on its parameters.
>
> If we make the optimization required on the keyword we would also need
> to require a diagnostic if the user broke the rules;  to actually
> produce such diagnostics the compiler would need to prove the function
> is _not_ actually deterministic.

    No, it's sufficient to require that the compiler detect anything
which COULD make the function non-deterministic.  Which is not
difficult.  Basically, any reference to a non-constant from outside
the function scope makes it not pure.  It's a relatively easy test,
similar to that performed for "private" class members.

> A compiler that actually is capable of proving a function has this
> deterministic property don't need a new keyword to make optimizations
> based on this knowledge. It is probably already doing it.

    Yes, wrote one of those in the 1980s.

    It's mainly a separate compilation issue.  It's not that hard to
examine a function for things which make it "not pure".  But
what do you do if the function calls a function from another
compilation unit?  You need a way to declare that the function
is "pure" in the declaration, then enforce that in the definition.

    I'm not sure this feature is worth the trouble, but if it's
going in, that's the way to do it.

   John Nagle

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "restor" <akrzemi1@interia.pl>
Date: Sat, 24 Mar 2007 09:18:48 CST
Raw View
> A "deterministic" keyword would not be much more useful than the
> current "inline" keyword.
>
> The only thing the standard can say about it is "this is a hint to a
> possible optimization the user would like".
> But specifying a deterministic keyword does not magically produce
> compilers capable to prove that any function has this deterministic
> property.
>
> If we make the optimization required on the keyword we would also need
> to require a diagnostic if the user broke the rules;  to actually
> produce such diagnostics the compiler would need to prove the function
> is _not_ actually deterministic.
>
> (Else, we mark rules breakage as undefined behaviour. Argh!)
>
> A compiler that actually is capable of proving a function has this
> deterministic property don't need a new keyword to make optimizations
> based on this knowledge. It is probably already doing it.
>
> I don't think we need new "hint to optimization" keywords.

The reason for having a keyword (or special syntax) would be:

1. to catch the situation where the user intended to make the function
'deterministic', but made a type-o, or forgot something. e.g.:

standard C++:

  double powA( double p1, double p2 ) {
      return x * y;
  }

  double powB( double p1, double p2 ) {
      std::clog << "computing pow" << std::endl;
      return x * y;
  }
  // powB has side effects, the programmer may not have realized
  // (and may not realize afterards

  double varA1 = powA( 3.1, 3.2 );
  double varA2 = powA( 3.1, 3.2 );   // no need to call powA again

  double varB1 = powB( 3.1, 3.2 );
  double varB2 = powB( 3.1, 3.2 );   // must call powB again

C++ with 'deterministic':

  double powA( double p1, double p2 ) deterministic {
      return x * y;
  }
  // 'deterministic' here is unnecessary: the compiler will
  // optimize anyway

  double powB( double p1, double p2 ) deterministic {
      std::clog << "computing pow" << std::endl;
      return x * y;
  }
  // compiler error: non-deterministic function called inside
  // a deterministic function.

2. Without the 'deterministic' keyword the compiler cannot optimize
calls to functions defined in another file:

extern double mySin( double a );
extern double myCos( double a );

double xa = x * myCos() + y * mySin();
double ya = x * mySin() - y * myCos();  // optimize or not?

'deterministic' here would enable optimization.

--------
&rzej



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: bop@gmb.dk ("Bo Persson")
Date: Sat, 24 Mar 2007 19:17:06 GMT
Raw View
restor wrote:
::
:: The reason for having a keyword (or special syntax) would be:
::
:: 1. to catch the situation where the user intended to make the
:: function 'deterministic', but made a type-o, or forgot something.
:: e.g.:

Why not a '#pragma nobugs' instead?  :-)

Changing the language to make it harder to write bad programs is geneally a
good idea. However, in this case i believe the savings will be extremely
small.

::
:: 2. Without the 'deterministic' keyword the compiler cannot optimize
:: calls to functions defined in another file:

Compilers can already inline functions across different compilation units. I
believe they can do this analysis as well.

::
:: extern double mySin( double a );
:: extern double myCos( double a );
::
:: double xa = x * myCos() + y * mySin();
:: double ya = x * mySin() - y * myCos();  // optimize or not?
::
:: 'deterministic' here would enable optimization.

But this is an optimization for this particular use of the functions. If
needed, you can introduce a few temporary variables to hold the values.

const double Cos = myCos();
const double Sin = mySin();

double xa = x * Cos + etc.


This is already available in the language. It also saves you from going back
to myCos definition to change it. If the optimization is needed right here,
why make the changes somewhere else?



Bo Persson



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: brangdon@ntlworld.com (Dave Harris)
Date: Sat, 24 Mar 2007 21:00:59 GMT
Raw View
alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura) wrote (abridged):
> I propose to have a special keyword to mark functions that will return
> the same value if the same arguments are given AND if only functions of
> a special kind (probably const) are called on the object.
>
>   class Container {
>     public:
>       int size() const deterministic;
>       Item& getAt(index i) const deterministic;
>       void add(Item item);
>   };

How would you deal with aliasing?

    static Container container;

    void proc( const Container &c ) {
        for (int i = 0; i < c.size(); ++i)
            container.add( c.getAt(i) );
    }

Should the compiler assume that c is not a reference to container? Or must
it suppress the optimisation? Or is this undefined behaviour?

-- Dave Harris, Nottingham, UK.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jose.diego@gmail.com" <jose.diego@gmail.com>
Date: Sun, 25 Mar 2007 23:36:27 CST
Raw View
On Mar 23, 2:57 pm, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
> <jose.di...@gmail.com> wrote in messagenews:1174505483.911510.39770@y66g2000hsf.googlegroups.com...
> > On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
> >> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> >> but somehow suppressed by other things. The concept of pure functions
> >> not only enables additional compiler optimizations, but also adds to
> >> the static safety of the code (like keyword const does). I also found
> >> it useful in refactoring long functions that may (or not) rely on
> >> static data.
>
> >> In the Container example, I think the 'deterministic' implies 'const',
> >> (it is even stronger). It would suffice to write:
>
> >> class Container {
> >>     public:
> >>       int size() deterministic; // is const because it is
> >> deterministic
> >>       Item& getAt(index i) deterministic; // const again
> >>       void add(Item item);
> >>   };
>
> > sorry, but I can't buy that in the container example
>
> > see:
>
> > while( somecondition() ) {
> >  somefuncion( container.size() );        // parameter will change
> > everytime. how deterministic will help here?
> >  container.add( something );
> > }
>
> Exactly. The idea of a deterministic function was that it depends only
> on its parameters. Since the parameters of size () are always the same
> (void), the result must be always the same. However, the result of
> size () is not always the same, it varies with the size of the container.
>
> If size () would be deterministic one could also argue that any function that
> depends on a global variable (or on any other property of the environment)
> could be deterministic. This would limit the optimization of deterministic
> functions a lot, because the compiler would no longer be able to know whether
> or not the environment has changed, so it must create a function call again to be
> sure to get the correct result.
> In this example the code for the add () function and the code for the size () function
> could be invisible for the compiler (just as the code of any member function of the
> container). The compiler does not know on which other object members the result
> of size () depends. So the result of size ()  may change after a call to any other member
> function or operator. So, there remains little opportunities for the compiler to optimize
> calls to size ().
> This means that other, true deterministic function, have also little opportunities for optimization.

yes

I can only figure out a "deterministic optimization" with methods when
using a const object (so, the const methods could be cached)

I do believe an optimizer can cache the results of a function that
does not mess with any global state (the beloved STL predicates are
good examples).
I am sure there is some script languages that do this optimization
using internal lookup tables. I can't recall what they are now.

Diego
HP

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "restor" <akrzemi1@interia.pl>
Date: Mon, 26 Mar 2007 08:41:07 CST
Raw View
> :: extern double mySin( double a );
> :: extern double myCos( double a );
> ::
> :: double xa = x * myCos() + y * mySin();
> :: double ya = x * mySin() - y * myCos();  // optimize or not?
> ::
> :: 'deterministic' here would enable optimization.
>
> But this is an optimization for this particular use of the functions. If
> needed, you can introduce a few temporary variables to hold the values.
>
> const double Cos = myCos();
> const double Sin = mySin();
>
> double xa = x * Cos + etc.
>
> This is already available in the language. It also saves you from going back
> to myCos definition to change it. If the optimization is needed right here,
> why make the changes somewhere else?

A very good point.

&rzej

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura)
Date: Tue, 27 Mar 2007 04:23:48 GMT
Raw View
Dave Harris escribi=F3:
> alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura) wrote (abridged):
>> I propose to have a special keyword to mark functions that will return
>> the same value if the same arguments are given AND if only functions o=
f
>> a special kind (probably const) are called on the object.
>>
>>   class Container {
>>     public:
>>       int size() const deterministic;
>>       Item& getAt(index i) const deterministic;
>>       void add(Item item);
>>   };
>=20
> How would you deal with aliasing?
>=20
>     static Container container;
>    =20
>     void proc( const Container &c ) {
>         for (int i =3D 0; i < c.size(); ++i)
>             container.add( c.getAt(i) );
>     }
>=20
> Should the compiler assume that c is not a reference to container? Or m=
ust=20
> it suppress the optimisation? Or is this undefined behaviour?
>=20
> -- Dave Harris, Nottingham, UK.

Oh! Got me.
I guess it should not optimize just in case they are the same. Or how do=20
compilers deal with other aliasing problems? IIRC there are flags like=20
"assume-no-aliasing" in some compilers to make them optimize things they=20
could not otherwise.

The optimization (caching) should be done only if no non-const functions=20
are called on *that* object. If there is a call to a non-const and it=20
can't be sure if they are the same or a different object, then it should=20
make the function call again normally.

I think there are currently similar conditions in the autovectorization=20
optimization in GCC, where possible aliasing disables lots of potential=20
optimizations.

> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with=
 ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu   =
 ]
> [              --- Please see the FAQ before posting. ---              =
 ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html                     =
 ]
>=20

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: nagle@animats.com (John Nagle)
Date: Tue, 27 Mar 2007 16:52:25 GMT
Raw View
Alvaro Segura wrote:
> Dave Harris escribi=F3:

>> How would you deal with aliasing?
>>
>>     static Container container;
>>         void proc( const Container &c ) {
>>         for (int i =3D 0; i < c.size(); ++i)
>>             container.add( c.getAt(i) );
>>     }
>>
>> Should the compiler assume that c is not a reference to container? Or=20
>> must it suppress the optimisation? Or is this undefined behaviour?

    When we used to do program verification work, we handled that by
writing something equivalent to:

static Container container;

void proc( const Container &c ) {
     assert(disjoint(c, container)); // programmer inserts this
     for (int i =3D 0; i < c.size(); ++i)
         container.add( c.getAt(i) );
}

This created a requirement at calls to "proc"
equivalent to writing

     assert(disjoint(tab, container)); // inserted by verifier
     proc(tab);

That's usually easy to evaluate at compile time to "true".

This is how real verifiers do design by contract.
This is too advanced for C++, though.

    John Nagle
    Animats



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jam" <farid.mehrabi@gmail.com>
Date: Tue, 27 Mar 2007 12:28:05 CST
Raw View
On Mar 23, 9:57 pm, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
> <jose.di...@gmail.com> wrote in messagenews:1174505483.911510.39770@y66g2000hsf.googlegroups.com...
> > On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
> >> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> >> but somehow suppressed by other things. The concept of pure functions
> >> not only enables additional compiler optimizations, but also adds to
> >> the static safety of the code (like keyword const does). I also found
> >> it useful in refactoring long functions that may (or not) rely on
> >> static data.
>
> >> In the Container example, I think the 'deterministic' implies 'const',
> >> (it is even stronger). It would suffice to write:
>
> >> class Container {
> >>     public:
> >>       int size() deterministic; // is const because it is
> >> deterministic
> >>       Item& getAt(index i) deterministic; // const again
> >>       void add(Item item);
> >>   };
>
> > sorry, but I can't buy that in the container example
>
> > see:
>
> > while( somecondition() ) {
> >  somefuncion( container.size() );        // parameter will change
> > everytime. how deterministic will help here?
> >  container.add( something );
> > }
>
> Exactly. The idea of a deterministic function was that it depends only
> on its parameters. Since the parameters of size () are always the same
> (void), the result must be always the same. However, the result of
> size () is not always the same, it varies with the size of the container.
>
> If size () would be deterministic one could also argue that any function that
> depends on a global variable (or on any other property of the environment)
> could be deterministic. This would limit the optimization of deterministic
> functions a lot, because the compiler would no longer be able to know whether
> or not the environment has changed, so it must create a function call again to be
> sure to get the correct result.
> In this example the code for the add () function and the code for the size () function
> could be invisible for the compiler (just as the code of any member function of the
> container). The compiler does not know on which other object members the result
> of size () depends. So the result of size ()  may change after a call to any other member
> function or operator. So, there remains little opportunities for the compiler to optimize
> calls to size ().
> This means that other, true deterministic function, have also little opportunities for optimization.
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]- Hide quoted text -
>
> - Show quoted text -

looks like we are forgetting that instance member methods get a hidden
'this' parameter too.So if the memeber functions is declared as
pure(deterministic ...) then it will act as a pure function if and
only if all the parameters including the hidden 'this'  parameter are
evaluated at compile time.Therefore we have to extend the keyword to
cover objects too:

struct A{
            A() deterministic;
            void f() deterministic;
};

deterministic A a;
a.f();//run at compile time
A b;
b.f();//evaluate at run time

IMHO deteministic is a synonym for literal but literal need not be
const.Take __LINE__ predefined macro for example; it is evaluated at
compile time but has different values in different places which means
it is a none-const literal(deterministic) value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jose.diego@gmail.com" <jose.diego@gmail.com>
Date: Wed, 21 Mar 2007 14:40:16 CST
Raw View
On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> but somehow suppressed by other things. The concept of pure functions
> not only enables additional compiler optimizations, but also adds to
> the static safety of the code (like keyword const does). I also found
> it useful in refactoring long functions that may (or not) rely on
> static data.
>
> In the Container example, I think the 'deterministic' implies 'const',
> (it is even stronger). It would suffice to write:
>
> class Container {
>     public:
>       int size() deterministic; // is const because it is
> deterministic
>       Item& getAt(index i) deterministic; // const again
>       void add(Item item);
>   };

sorry, but I can't buy that in the container example

see:

while( somecondition() ) {
  somefuncion( container.size() );        // parameter will change
everytime. how deterministic will help here?
  container.add( something );
}

Diego
HP

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura)
Date: Fri, 23 Mar 2007 05:03:42 GMT
Raw View
Grizlyk escribi=F3:
> Alvaro Segura wrote:
>>  x =3D a*sin(t) + b*cos(t);
>>  y =3D c*sin(t) + b*cos(t);
>>
>> If the compiler knew sin(t) and cos(t) always return the same value, f=
or
>> the same t, they could cache the results and avoid costly function
>> calls, because t does not change between those lines.
>=20
> I think the main problem is that the function is working not at compile=
=20
> time, but at run time.
>=20
> What kind of memory must be in C++ to cache the results?
> What way compiler must use to realize, that argument is cached?

If I had mere arithmetic expressions like:

  x =3D (a + b*k) * t1;
  y =3D (a + b*k) * t2

Compilers will probably identify the (a+b*k) subexpression which keeps=20
its value in both lines and would therefore produce something equivalent =
to:

  tmp =3D (a + b*k);
  x =3D tmp * t1;
  y =3D tmp * t2;

My idea was to extend this kind of automatic optimization to expressions=20
involving function calls, for which the compiler is currently blind. It=20
has to repeat function calls dumbly even if we know it can be simplified=20
(and we can do it by hand, but that's not the point).

And especially in the case of *member functions*.

I relate this kind of semantics to the idea of "properties" (either via=20
  normal accessor member functions or via special language constructs=20
[that I would strongly support :-)]). Property getters would be=20
deterministic by default, because they return something related to the=20
current *logic state* of the object, and the logic state does not change=20
when *const* functions are called on the object.

> if you need table of sin/cos, you can generate and use the table:
>=20
> inline double sin() { return sin_table[adjust(arg)]; }
>=20
>> Well, maybe
>> compilers know these two common functions, but consider they could be
>> any complex user defined function (a*strange_function(t)).
>>
>> Consider:
>>
>>  for(int i=3D0; i < v.size(); i++)
>>    v[i]++;
>>
>> Here, the compiler will evaluate v.size() on every loop iteration, but
>> we know the size of the vector will remain the same throughout the loo=
p.
>=20
> You can use explicit temporary
>=20
> const int items=3Dv.size()
>     for(int i=3D0; i < items; ++i)v[i]++;
>=20
> or reverse order of counting
>=20
> vector::iterator it( v.begin() );
>     for(int i=3Dv.size(); i ; --i)(*it++)++;
>=20
>=20
> But there is interesting thing here, we can make implicit temporary wit=
h=20
> "once":
>=20
>>  for(int i=3D0; i < v.size() once; ++i)v[i]++;
>=20
> here v.size() will be called as if has been declared
>=20
>     for(int i=3D0, /*const int*/ _tmp=3Dv.size(); i< _tmp; ++i)
>=20
>=20

Mmm... this "once" thing exists or it's a proposal?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura)
Date: Fri, 23 Mar 2007 05:45:18 GMT
Raw View
jose.diego@gmail.com escribi=F3:
> On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
>> I believe it was already considered by the C++ Standards Committee:htt=
p://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
>> but somehow suppressed by other things. The concept of pure functions
>> not only enables additional compiler optimizations, but also adds to
>> the static safety of the code (like keyword const does). I also found
>> it useful in refactoring long functions that may (or not) rely on
>> static data.
>>
>> In the Container example, I think the 'deterministic' implies 'const',
>> (it is even stronger). It would suffice to write:
>>
>> class Container {
>>     public:
>>       int size() deterministic; // is const because it is
>> deterministic
>>       Item& getAt(index i) deterministic; // const again
>>       void add(Item item);
>>   };
>=20
> sorry, but I can't buy that in the container example
>=20
> see:
>=20
> while( somecondition() ) {
>   somefuncion( container.size() );        // parameter will change
> everytime. how deterministic will help here?
>   container.add( something );
> }
>=20

There is no problem:

The add() functionis NOT const, then the compiler knows it may affect=20
the result of deterministic functions, so it will NOT cache the result=20
of size() in this case for the next iteration.

if instead of add() we called other *inspecting* (i.e. getter, *const*)=20
member functions the size() and other deterministic functions will not=20
need to be called again.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Fred Zwarts" <F.Zwarts@KVI.nl>
Date: Fri, 23 Mar 2007 11:57:52 CST
Raw View
<jose.diego@gmail.com> wrote in message news:1174505483.911510.39770@y66g2000hsf.googlegroups.com...
> On Mar 17, 12:42 pm, "restor" <akrze...@interia.pl> wrote:
>> I believe it was already considered by the C++ Standards Committee:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
>> but somehow suppressed by other things. The concept of pure functions
>> not only enables additional compiler optimizations, but also adds to
>> the static safety of the code (like keyword const does). I also found
>> it useful in refactoring long functions that may (or not) rely on
>> static data.
>>
>> In the Container example, I think the 'deterministic' implies 'const',
>> (it is even stronger). It would suffice to write:
>>
>> class Container {
>>     public:
>>       int size() deterministic; // is const because it is
>> deterministic
>>       Item& getAt(index i) deterministic; // const again
>>       void add(Item item);
>>   };
>
> sorry, but I can't buy that in the container example
>
> see:
>
> while( somecondition() ) {
>  somefuncion( container.size() );        // parameter will change
> everytime. how deterministic will help here?
>  container.add( something );
> }

Exactly. The idea of a deterministic function was that it depends only
on its parameters. Since the parameters of size () are always the same
(void), the result must be always the same. However, the result of
size () is not always the same, it varies with the size of the container.

If size () would be deterministic one could also argue that any function that
depends on a global variable (or on any other property of the environment)
could be deterministic. This would limit the optimization of deterministic
functions a lot, because the compiler would no longer be able to know whether
or not the environment has changed, so it must create a function call again to be
sure to get the correct result.
In this example the code for the add () function and the code for the size () function
could be invisible for the compiler (just as the code of any member function of the
container). The compiler does not know on which other object members the result
of size () depends. So the result of size ()  may change after a call to any other member
function or operator. So, there remains little opportunities for the compiler to optimize
calls to size ().
This means that other, true deterministic function, have also little opportunities for optimization.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "=?iso-8859-1?q?Pedro_Lamar=E3o?=" <pedro.lamarao@gmail.com>
Date: Fri, 23 Mar 2007 19:24:11 CST
Raw View
On 23 mar, 14:57, "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:

> Exactly. The idea of a deterministic function was that it depends only
> on its parameters. Since the parameters of size () are always the same
> (void), the result must be always the same. However, the result of
> size () is not always the same, it varies with the size of the container.

A "deterministic" keyword would not be much more useful than the
current "inline" keyword.

The only thing the standard can say about it is "this is a hint to a
possible optimization the user would like".
But specifying a deterministic keyword does not magically produce
compilers capable to prove that any function has this deterministic
property.

If we make the optimization required on the keyword we would also need
to require a diagnostic if the user broke the rules;  to actually
produce such diagnostics the compiler would need to prove the function
is _not_ actually deterministic.

(Else, we mark rules breakage as undefined behaviour. Argh!)

A compiler that actually is capable of proving a function has this
deterministic property don't need a new keyword to make optimizations
based on this knowledge. It is probably already doing it.

I don't think we need new "hint to optimization" keywords.

--
 Pedro Lamar   o


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Fri, 23 Mar 2007 20:48:02 CST
Raw View
Alvaro Segura ha scritto:
> Grizlyk escribi   :
>>
>> But there is interesting thing here, we can make implicit temporary
>> with "once":
>>
>>>  for(int i=0; i < v.size() once; ++i)v[i]++;
>>
>> here v.size() will be called as if has been declared
>>
>>     for(int i=0, /*const int*/ _tmp=v.size(); i< _tmp; ++i)
>>
>>
>
> Mmm... this "once" thing exists or it's a proposal?

It definitely does *not* exist. And I doubt strongly that it will ever
exist in the future. The applicability of such construct is limited to
this particular case of for statements. The scope is so narrow that I
don't see the real advantage.

BTW, there is a proposal about the for statement that is much more
interesting and superior:
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf>.

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Grizlyk" <grizlyk1@yandex.ru>
Date: Tue, 20 Mar 2007 11:19:40 CST
Raw View
Alvaro Segura wrote:
>
>  x = a*sin(t) + b*cos(t);
>  y = c*sin(t) + b*cos(t);
>
> If the compiler knew sin(t) and cos(t) always return the same value, for
> the same t, they could cache the results and avoid costly function
> calls, because t does not change between those lines.

I think the main problem is that the function is working not at compile
time, but at run time.

What kind of memory must be in C++ to cache the results?
What way compiler must use to realize, that argument is cached?

if you need table of sin/cos, you can generate and use the table:

inline double sin() { return sin_table[adjust(arg)]; }

> Well, maybe
> compilers know these two common functions, but consider they could be
> any complex user defined function (a*strange_function(t)).
>
> Consider:
>
>  for(int i=0; i < v.size(); i++)
>    v[i]++;
>
> Here, the compiler will evaluate v.size() on every loop iteration, but
> we know the size of the vector will remain the same throughout the loop.

You can use explicit temporary

const int items=v.size()
    for(int i=0; i < items; ++i)v[i]++;

or reverse order of counting

vector::iterator it( v.begin() );
    for(int i=v.size(); i ; --i)(*it++)++;


But there is interesting thing here, we can make implicit temporary with
"once":

>  for(int i=0; i < v.size() once; ++i)v[i]++;

here v.size() will be called as if has been declared

    for(int i=0, /*const int*/ _tmp=v.size(); i< _tmp; ++i)


--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "restor" <akrzemi1@interia.pl>
Date: Sat, 17 Mar 2007 09:42:51 CST
Raw View
I believe it was already considered by the C++ Standards Committee:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
but somehow suppressed by other things. The concept of pure functions
not only enables additional compiler optimizations, but also adds to
the static safety of the code (like keyword const does). I also found
it useful in refactoring long functions that may (or not) rely on
static data.

In the Container example, I think the 'deterministic' implies 'const',
(it is even stronger). It would suffice to write:

class Container {
    public:
      int size() deterministic; // is const because it is
deterministic
      Item& getAt(index i) deterministic; // const again
      void add(Item item);
  };

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 19 Mar 2007 16:40:02 GMT
Raw View
restor wrote:
> I believe it was already considered by the C++ Standards Committee:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> but somehow suppressed by other things. The concept of pure functions
> not only enables additional compiler optimizations, but also adds to
> the static safety of the code (like keyword const does). I also found
> it useful in refactoring long functions that may (or not) rely on
> static data.

     The definition of "pure" functions there is potentially unsafe.
The concept that a "pure" function can access "const" parameters
"as long as we require that no non-pure function that has write
access to the argument runs in parallel with it" isn't enforceable
by the compiler without other, substantial language changes.
C++ needs to know far more about parallelism than it does to
make that a workable rule.

     A narrower, more traditional definition will work.
The basic requirement for "pure" functions is that

 x == y implies f(x) == f(y)

and that the function has no side effects.

Given this, compilers can safely merge, hoist, and parallelize calls
to pure functions.

     All the mathematical functions (sin(), cos(), etc.) should be made
"pure", of course.

     Member functions of an object cannot be "pure".  They have
external non-constant inputs.

     A question is whether "pure" functions should be allowed to modify
their own arguments.  Consider

 void invert_matrix(float m[4][4]) pure;

which presumably alters its argument.  Should that be considered "pure"?
I would say "yes".  The compiler knows that the argument is non-const,
so it knows to not assume that it won't change as part of the call.

A good use case for the utility of the "pure" concept is whether
the functions in "Numerical Recipes in C++" can be modified to work
with most functions "pure".

    John Nagle

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tasjaevan@gmail.com
Date: Mon, 19 Mar 2007 12:18:50 CST
Raw View
"John Nagle" wrote:
>
>     All the mathematical functions (sin(), cos(), etc.) should be made
> "pure", of course.
>
>     Member functions of an object cannot be "pure".  They have
> external non-constant inputs.
>

Why the distinction between

  UserType inverse(const UserType&);

and

  class UserType
  {
  public:
    UserType inverse() const;
  };

?

Surely they can both be "pure".

James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jam" <farid.mehrabi@gmail.com>
Date: Mon, 19 Mar 2007 17:04:48 CST
Raw View
On Mar 19, 8:40 pm, n...@animats.com (John Nagle) wrote:
> restor wrote:
> > I believe it was already considered by the C++ Standards Committee:
> >http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1703.pdf
> > but somehow suppressed by other things. The concept of pure functions
> > not only enables additional compiler optimizations, but also adds to
> > the static safety of the code (like keyword const does). I also found
> > it useful in refactoring long functions that may (or not) rely on
> > static data.
>
>      The definition of "pure" functions there is potentially unsafe.
> The concept that a "pure" function can access "const" parameters
> "as long as we require that no non-pure function that has write
> access to the argument runs in parallel with it" isn't enforceable
> by the compiler without other, substantial language changes.
> C++ needs to know far more about parallelism than it does to
> make that a workable rule.
>
>      A narrower, more traditional definition will work.
> The basic requirement for "pure" functions is that
>
>         x == y implies f(x) == f(y)
>
> and that the function has no side effects.
>
> Given this, compilers can safely merge, hoist, and parallelize calls
> to pure functions.
>
>      All the mathematical functions (sin(), cos(), etc.) should be made
> "pure", of course.
>
>      Member functions of an object cannot be "pure".  They have
> external non-constant inputs.
>
>      A question is whether "pure" functions should be allowed to modify
> their own arguments.  Consider
>
>         void invert_matrix(float m[4][4]) pure;
>
> which presumably alters its argument.  Should that be considered "pure"?
> I would say "yes".  The compiler knows that the argument is non-const,
> so it knows to not assume that it won't change as part of the call.
>
> A good use case for the utility of the "pure" concept is whether
> the functions in "Numerical Recipes in C++" can be modified to work
> with most functions "pure".
>
>                                 John Nagle
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]

I believe in the distinction between the words constant and literal:
constant means sth supposed not to change after construction.
literal means the data processed in preparation phase of programs not
at runtime.
As an example the __LINE__ macro is a literal which obviosly is not
constant since it alters its meaning in every different line of
code.It is processed at compile time and used at run time.
I think we need functions and classes producing this sort of data by
which means I can get rid of a resource compiler and its specific
syntax.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "jam" <farid.mehrabi@gmail.com>
Date: Thu, 15 Mar 2007 12:35:59 CST
Raw View
On Mar 13, 9:17 pm, fran...@robinton.demon.co.uk (Francis Glassborow)
wrote:
> In article <1173749196.597467.294...@30g2000cwc.googlegroups.com>,
> Mathias Gaunard <loufo...@gmail.com> writes
>
> >On Mar 12, 6:02 pm, alvaro.segura.SPAMF...@gmail.com (Alvaro Segura)
> >wrote:
>
> >> I propose to have a special keyword to mark functions that will return
> >> the same value if the same arguments are given AND if only functions of
> >> a special kind (probably const) are called on the object.
>
> >Isn't that the same as constexpr ?
>
> I don't think so. It seems to me to be rather more like the concept of a
> pure function because given the same input such a function must return
> the same value and cannot have any side-effects.
>
> --
> Francis Glassborow      ACCU
> Author of 'You Can Do It!' and "You Can Program in C++"
> seehttp://www.spellen.org/youcandoit
> For project ideas and contributions:http://www.spellen.org/youcandoit/projects
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]

I humbly suggest the name of multi-stage programing as a new paradigm
related to this post in short words we want to tell the compiler that
whenevever - posible - calculates a value at compile time rather than
run time, hence decrease both runtime and memory overhead at
once.Considering  *JIT*(Just In Time compiling) we can extend the
number phases at which the value is evaluated to three steps:
I.design:
  on the programers platform when the code is generated.
II.install:
  when the program is completeltly built in the target machine.
III.run:
  when the program is finally executed.

We want the compiler to be able to run some user defined code at
design or installation time.

consider this :

template<int>struct A{};
int pow(int,int);

now the following line results in compile error:

A<pow(1,2)> a;//error: parameter to template should have internal
linkage

it would be fine if we could write:

design int pow(int,int);//evaluate the result at design phase whenever
posible
install int size(int);//evaluate the result at install phase whenever
posible
int go();

A<pow(1,2)> ap;//ok pow is evaluated at design phase.
A<size(3)> as;//ok pow is evaluated at install phase.
A<go()> ag;//error: go is evaluated at run time.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: alvaro.segura.SPAMFREE@gmail.com (Alvaro Segura)
Date: Mon, 12 Mar 2007 17:02:02 GMT
Raw View
This is a proposal for a language feature with an added potential
benefit as a hint to compiler optimization. It is just an idea, consider
the (bad) examples as an illustration of it.

Compilers are good at eliminating common subexpressions (i.e. evaluating
them once and caching the result), but they can do nothing if
expressions involve functions that may or may not give expected results.

Consider:

  x = a*sin(t) + b*cos(t);
  y = c*sin(t) + b*cos(t);

If the compiler knew sin(t) and cos(t) always return the same value, for
the same t, they could cache the results and avoid costly function
calls, because t does not change between those lines. Well, maybe
compilers know these two common functions, but consider they could be
any complex user defined function (a*strange_function(t)).

Consider:

  for(int i=0; i < v.size(); i++)
    v[i]++;

Here, the compiler will evaluate v.size() on every loop iteration, but
we know the size of the vector will remain the same throughout the loop.

Of course, many functions will need to be always called (imagine things
like clock(), device.read(ptr, n)).

I propose to have a special keyword to mark functions that will return
the same value if the same arguments are given AND if only functions of
a special kind (probably const) are called on the object.

Then:

  double sin(double x) deterministic;

  class Container {
    public:
      int size() const deterministic;
      Item& getAt(index i) const deterministic;
      void add(Item item);
  };

I'm not sure the requirement of only calling const functions in order to
cache a deterministic member function value is a good one. Maybe a
different specifier would be needed. Optimally (but impractically) a map
of what functions affect the value of what functions would be ideal, I
guess.

My examples here are probably not good, but I have often come to
situations in practical problems were this feature would help a lot.

A feature like this would impose a "deterministic correctness" in C++
designs similar to the current "const correctness", and I see good
potential for hinting optimizing compilers.

Maybe this has already been discussed but I have not seen anything like it.

Any comments or doubts about the idea?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Mathias Gaunard" <loufoque@gmail.com>
Date: Tue, 13 Mar 2007 00:25:57 CST
Raw View
On Mar 12, 6:02 pm, alvaro.segura.SPAMF...@gmail.com (Alvaro Segura)
wrote:

> I propose to have a special keyword to mark functions that will return
> the same value if the same arguments are given AND if only functions of
> a special kind (probably const) are called on the object.

Isn't that the same as constexpr ?


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Tue, 13 Mar 2007 17:17:50 GMT
Raw View
In article <1173749196.597467.294540@30g2000cwc.googlegroups.com>,
Mathias Gaunard <loufoque@gmail.com> writes
>On Mar 12, 6:02 pm, alvaro.segura.SPAMF...@gmail.com (Alvaro Segura)
>wrote:
>
>> I propose to have a special keyword to mark functions that will return
>> the same value if the same arguments are given AND if only functions of
>> a special kind (probably const) are called on the object.
>
>Isn't that the same as constexpr ?


I don't think so. It seems to me to be rather more like the concept of a
pure function because given the same input such a function must return
the same value and cannot have any side-effects.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]