This is the mail archive of the gsl-discuss@sources.redhat.com mailing list for the GSL project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Parameter vectors declared as const in minimized functions


On Wed, 5 Jan 2005, Linas Vepstas wrote:

> > > int f (const int *arg)
> > >   {
> > >   int *my_arg;
> > >   my_arg = arg;
> > >   if (*my_arg > 5) *my_arg -= 5;
> > >   return *my_arg+2;
> > >   }
> 
> This is very wrong, you are violating the const'ness of the array.
> Compilers can do optimizations based on the assumed constness of 
> things; by violating it in this way, you will get bizarre and 
> invalid results, depending on the optimizations taken.

OK, live and learn, and thanks for the lesson.  I simply never use(d)
const int *arg-like constructions in argument lists because when I write
code passing back values via pointers is a deliberate choice made per
function.  OTOH, I can see where one might need such a thing in a
subroutine library where the calling routine needs to be certain that
the parameters it passed to the function aren't changed in mid-loop.

Just as a matter of curiosity (and because I truly do believe that RTFM
is an excellent first step to learning) where is this documented --
preferrably online?  As I said, the three C tutorials I have accessible
pass over this entirely and don't address the issue of

 int i;
 for(i=0;i<10;i++) f(&i);

plus

 int f(const int *arg)
 {
            /* do some work here ending in */
    *arg--; /* or whatever -- causes an incidental infinite loop */
 }

which is the kind of stuff that I presume the const modifier is intended
to prevent.  They only discuss mundane usage such as

 const int moon_landing = 1969;

etc. (e.g. Gnu C Programming Manual).  I should probably dig out my
paper copy of K&R and see if it is discussed therein...


In the "more than one way to do things" spirit, though, let me suggest a
few other legal ways to cause the same effect as direct modification
that the compiler shouldn't complain about.  How about:

int j,k;
main()
{
 int i = 100;
 j = i;

 while(i>0){
   i = j;
   f(&i);
 }
}

int f(const int *arg)
{
 if(check(arg,k)){
   j = *arg - 1;
   k = *arg + 1;
 } else {
   j = *arg + 2;
   k = *arg - 1;
 }
}

The subroutine now leaves *arg strictly alone, but arranges to pass back
conditional modifications to *arg (really i) back in a global variable
j, which is in turn used to set i in the calling routine for the next
call, while "remembering" some dependent information in a shared
variable k that is also used in future steps to affect the behavior of
f().  

Not that this particular code is necessarily sensible functionally, but
this seems to be an apropos suggestion for a solution to the original
poster's problem.  I spend a fair bit of time integrating coupled ODEs
(another case where one has to provide a pointer to a function with
strict rules concerning what can change during a call) and of course
with COUPLED ODEs there are all sorts of complex ways where a shared
variable set can be modified per call and used to determine behavior of
f() in future calls. I also have written programs that optimize on a
couple or four hundred dimensions using neural networks with moderately
complex fitness functions, ditto.  I generally just put "coupling"
variables and non-markovian "memory" variables that the routine itself
might need to generate future f()'s per call into global memory where
f() can modify them at will while leaving its actual
library-routine-required argument lists (const or not) alone.

So (to the original poster) consider using global variables to
accomplish what it is that you'd like to do by modifying the arguments,
while leaving the calling optimization routines secure in their belief
that when it passed they passed in a vector of parameter values to
evaluate the fitness/optimization value at a point that the coordinates
of that point aren't spontaneously changed out from underneath it during
the call.  

If this still won't work for you, you may end up having to do another
thing I've resorted to in the past -- grab the source, hack out the
const modifier AND work your way through the calling routines to be sure
that this does what you want it to do without side effects like infinite
loops or just not working, and then run to your heart's content.

Much as I love numerical libraries in general as they keep me from
having to go back to my personal "library" of routines culled from all
sorts of places and written directly from Abramowitz and Stegun (many of
which aren't going to be as robust and thoroughly tested as the GSL
routines are), the fact that the GSL in particular is fully open source
is a tremendous, overwhelming advantage for just this reason.  So much
so that I honestly think that non-Open Source numerical libraries are
just plain Wrong.  There are indeed times that one encounters a problem
that is really difficult to solve using the preordained call format for
some numerical tool, or have a problem where performance is so critical
that the overhead of working through a library call matters.  In those
cases the source is right there at your disposal, and with care you can
still use the algorithms therein without having to re-research and code
them but make critical modifications to inline embed them into your code
or permit things like varying argument lists.

   rgb

-- 
Robert G. Brown	                       http://www.phy.duke.edu/~rgb/
Duke University Dept. of Physics, Box 90305
Durham, N.C. 27708-0305
Phone: 1-919-660-2567  Fax: 919-660-2525     email:rgb@phy.duke.edu



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]