From: Charles Coldwell on
glen herrmannsfeldt <gah(a)ugcs.caltech.edu> writes:

> Charles Coldwell wrote:
> (snip)
>
>> In C, I would write this
>
>> int compare(int i, int j)
>> {
>> double r = data[i] - data[j];
>> return (2*(r>0) - 1) & -(r != 0);
>> }
>
> I think I more often see:
>
> return (r>0)-(r<0);

Oooh. I like that.

> Otherwise, how about
>
> compare=count((/ data[i].ge.data[j], data[i].gt.data[j] /))-1

Very cute, I like it, too. I have more confidence in the compiler's
ability to generate tight code for the C version, above, though.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"
GPG Key ID: 852E052F
GPG Key Fingerprint: 77E5 2B51 4907 F08A 7E92 DE80 AFA9 9A8F 852E 052F
From: relaxmike on
On 23 avr, 12:06, Charles Coldwell <coldw...(a)gmail.com> wrote:
> I don't see any code duplication in the client. The implementations
> of "compare" and "exchange" must be different for different types.
> It's like in C++, where "operator<" (the analog of "compare") must be
> defined for any type in an STL container.

I think I now understand what you mean, and let me explain what
I mean : there is no duplication in the client, simply because there
is only one client, of course ! This is because you transformed
the problem of "having a method which sorts whatever type of array"
into "having a method which sorts the client-side array".
The consequence is that you define only one "compare" method, and
you conclude that there is no duplication.

Now let's define what should be to do to have a method to
sort arrays of logical, integers, real and double :
you, of course, have to define a "compare_logical" ,
"compare_integer",
"compare_real", "compare_double". This is because the compare method
have to explicitly define the type of data to compare.
In the end, there are 4 implementations of the same "template"
compare, all using the same (and basic) "<".
That is true that if you want to compare characters, you may have to
define "<" (but I am not sure).
Isn'it duplication ?

I looked in the internet to search for how the C++ STL solved that
problem. I found a web page, but I do not known if it is of high
quality :
http://www.cppreference.com/cppalgorithm/sort.html
See how the sort of an array of integers is solved :

vector<int> v;
v.push_back( 23 );
v.push_back( -1 );
v.push_back( 9999 );
v.push_back( 0 );
v.push_back( 4 );
sort( v.begin(), v.end() );

I don't pretend that fortran can achieve such a level of
simplicity, but that's the goal isn't it ?
I think that callbacks are a good and efficient way
to uncouple the sorting algorithm from the type of
data to sort, but that is only half of the work to do
to have a routine which can sort <whatever> type of
array.

Regards,

Michaël
From: Greg Lindahl on
In article <9b4f7b86-02ae-4717-b375-e7314e1798c0(a)l64g2000hse.googlegroups.com>,
relaxmike <michael.baudin(a)gmail.com> wrote:

>See how the sort of an array of integers is solved :
>
> vector<int> v;
> v.push_back( 23 );
> v.push_back( -1 );
> v.push_back( 9999 );
> v.push_back( 0 );
> v.push_back( 4 );
> sort( v.begin(), v.end() );
>
>I don't pretend that fortran can achieve such a level of
>simplicity, but that's the goal isn't it ?

You've got to be kidding! Variables that lack a constructor syntax are
not that simple. And the STL is well known to have a pretty steep
learning curve.

-- greg


From: Charles Coldwell on
relaxmike <michael.baudin(a)gmail.com> writes:

> On 23 avr, 12:06, Charles Coldwell <coldw...(a)gmail.com> wrote:
>> I don't see any code duplication in the client. The implementations
>> of "compare" and "exchange" must be different for different types.
>> It's like in C++, where "operator<" (the analog of "compare") must be
>> defined for any type in an STL container.
>
> I think I now understand what you mean, and let me explain what
> I mean : there is no duplication in the client, simply because there
> is only one client, of course ! This is because you transformed
> the problem of "having a method which sorts whatever type of array"
> into "having a method which sorts the client-side array".
> The consequence is that you define only one "compare" method, and
> you conclude that there is no duplication.
>
> Now let's define what should be to do to have a method to
> sort arrays of logical, integers, real and double :
> you, of course, have to define a "compare_logical" ,
> "compare_integer",
> "compare_real", "compare_double". This is because the compare method
> have to explicitly define the type of data to compare.
> In the end, there are 4 implementations of the same "template"
> compare, all using the same (and basic) "<".
> That is true that if you want to compare characters, you may have to
> define "<" (but I am not sure).
> Isn'it duplication ?

Yes and no. It's more duplication than what you find in C++. For
example, to use an ordered STL container, a class must define
"operator<". For POD types (int, long, double, float), you can use
the built-in compiler provided operator, you don't have to write any
code, whereas in my Fortran quicksort-with-callbacks, you must define
"compare", even for the built-in types (e.g. INTEGER, REAL, LOGICAL).
However, if you want to sort *strings*, you will have to define
"operator<" for the string class. Similarly for any user-defined
types. Now, admittedly, "operator<" for std::string comes with the
standard library, so you would be crazy to actually write it yourself,
but you still have to define it for all the types you design yourself.

> I looked in the internet to search for how the C++ STL solved that
> problem. I found a web page, but I do not known if it is of high
> quality :
> http://www.cppreference.com/cppalgorithm/sort.html
> See how the sort of an array of integers is solved :
>
> vector<int> v;
> v.push_back( 23 );
> v.push_back( -1 );
> v.push_back( 9999 );
> v.push_back( 0 );
> v.push_back( 4 );
> sort( v.begin(), v.end() );
>
> I don't pretend that fortran can achieve such a level of
> simplicity, but that's the goal isn't it ?

Sure. What I wrote is a Fortran function that implements the "sort"
that comes with the C++ standard library. You could argue that
Fortran should supply a sort intrinsic so that the code isn't
duplicated by many implementors, but that's different from generic
programming. In terms of simplicity, if I wrote a module implementing
compare and exchange for integers, the C++ code above in Fortran would
read

use my_module
data(1) = 23
data(2) = -1
data(3) = 9999
data(4) = 0
data(5) = 4
call quicksort(5, compare, exchange)

The difference with C++ in this example is that the standard library
is supplying the sort routine, the vector<> template and it's
associated "operator<" (which in this case is just the built-in
"operator<" for type int). The quicksort routine I posted previously
is almost as general as the one that the C++ standard library
supplies: it can work on an array of any type, including user-defined
types, hence my claim that it demonstrates "generic programming" in
Fortran. The C++ STL sort is more generic because it works on
containers of any type, including lists, deques, arrays, vectors, maps
and multimaps.

> I think that callbacks are a good and efficient way
> to uncouple the sorting algorithm from the type of
> data to sort,

Hence my claim that it is "generic".

> but that is only half of the work to do to have a routine which can
> sort <whatever> type of array.

Fair enough, but at least for user-defined types, you have to do the
other half of the work yourself whether you use C++ or Fortran.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"
GPG Key ID: 852E052F
GPG Key Fingerprint: 77E5 2B51 4907 F08A 7E92 DE80 AFA9 9A8F 852E 052F
From: relaxmike on
On 24 avr, 12:36, Charles Coldwell <coldw...(a)gmail.com> wrote:
> Yes and no. It's more duplication than what you find in C++. For
> example, to use an ordered STL container, a class must define
> "operator<". For POD types (int, long, double, float), you can use
> the built-in compiler provided operator, you don't have to write any
> code, whereas in my Fortran quicksort-with-callbacks, you must define
> "compare", even for the built-in types (e.g. INTEGER, REAL, LOGICAL).
> However, if you want to sort *strings*, you will have to define
> "operator<" for the string class. Similarly for any user-defined
> types. Now, admittedly, "operator<" for std::string comes with the
> standard library, so you would be crazy to actually write it yourself,
> but you still have to define it for all the types you design yourself.

Yes of course, you are right.
I cannot consider that defining three compare routines is such a
big deal that one should use a template for that.
We agree that the callback method is more closed to generic
programming
that it is to templates.

> The difference with C++ in this example is that the standard library
> is supplying the sort routine, the vector<> template and it's
> associated "operator<" (which in this case is just the built-in
> "operator<" for type int). The quicksort routine I posted previously
> is almost as general as the one that the C++ standard library
> supplies: it can work on an array of any type, including user-defined
> types, hence my claim that it demonstrates "generic programming" in
> Fortran. The C++ STL sort is more generic because it works on
> containers of any type, including lists, deques, arrays, vectors, maps
> and multimaps.

Obviously, I don't know the STL sufficiently to compare fortran and
C++ at that level. And I do not master the C++ iterators.

> Fair enough, but at least for user-defined types, you have to do the
> other half of the work yourself whether you use C++ or Fortran.

You are right and there is no other way to do it.
Anyway, the algorithm you provided is an interesting solution for the
generic sorting problem.

Michaël