# writing an external function in std c++

G

#### Gerry Ford

I've been pecking away at writing a program that will calculate the inner
product of two double-width four-vectors.

Larry thinks I'm well started with the following source to populate a
vector:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <math.h>

int main() {
std::vector<double> four_vector;

for (double i=0.0; i<4.0; i++)
four_vector.push_back(sqrt(i));

std::cout.precision(16);

std::copy(four_vector.begin(), four_vector.end(),
std: stream_iterator<double>(std::cout, "\n"));
return 0;
}

How do I imitate the following fortran source:
program vector2
implicit none
integer index, i
integer, parameter :: some_kind_number = selected_real_kind (p=16)
real (kind = some_kind_number), dimension(4):: vec_a, vec_b
real (kind = some_kind_number) :: res

index = 4

do i = 1, index
vec_a(i)= i**.5

vec_b(i)= (-1)*(i**2)

end do

res = dot_product(vec_a, vec_b)

write (*,*) vec_a, vec_b
write (*,*) res

end program vector2

! gfortran2 -o vector2 vector2.f95
! vector2 >text55.txt 2>text56.txt
//end source continue comment
, except making the inner product calculated externally. I have zero chance
of getting it correct, so I'll spare you the flailing attempt. Screenshot
here: http://zaxfuuq.net/c++5.jpg

To imitate it, I believe the appropriate c++ inner product would be around
negative 25.

K

#### Kai-Uwe Bux

Gerry said:
I've been pecking away at writing a program that will calculate the inner
product of two double-width four-vectors.

Larry thinks I'm well started with the following source to populate a
vector:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <math.h>

int main() {
std::vector<double> four_vector;

for (double i=0.0; i<4.0; i++)
four_vector.push_back(sqrt(i));

std::cout.precision(16);

std::copy(four_vector.begin(), four_vector.end(),
std: stream_iterator<double>(std::cout, "\n"));
return 0;
}

How do I imitate the following fortran source:
program vector2
implicit none
integer index, i
integer, parameter :: some_kind_number = selected_real_kind (p=16)
real (kind = some_kind_number), dimension(4):: vec_a, vec_b
real (kind = some_kind_number) :: res

index = 4

do i = 1, index
vec_a(i)= i**.5

vec_b(i)= (-1)*(i**2)

end do

res = dot_product(vec_a, vec_b)

write (*,*) vec_a, vec_b
write (*,*) res

end program vector2

! gfortran2 -o vector2 vector2.f95
! vector2 >text55.txt 2>text56.txt
//end source continue comment
, except making the inner product calculated externally. I have zero
chance
of getting it correct, so I'll spare you the flailing attempt. Screenshot
here: http://zaxfuuq.net/c++5.jpg

To imitate it, I believe the appropriate c++ inner product would be around
negative 25.

std::inner_product( vec_a.begin(), vec_a.end(), vec_b.begin(), double() );

Best

Kai-Uwe Bux

J

#### Jim Langston

Gerry said:
I've been pecking away at writing a program that will calculate the
inner product of two double-width four-vectors.

Larry thinks I'm well started with the following source to populate a
vector:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <math.h>

int main() {
std::vector<double> four_vector;

for (double i=0.0; i<4.0; i++)
four_vector.push_back(sqrt(i));

std::cout.precision(16);

std::copy(four_vector.begin(), four_vector.end(),
std: stream_iterator<double>(std::cout, "\n"));
return 0;
}

How do I imitate the following fortran source:
program vector2
implicit none
integer index, i
integer, parameter :: some_kind_number = selected_real_kind (p=16)
real (kind = some_kind_number), dimension(4):: vec_a, vec_b
real (kind = some_kind_number) :: res

index = 4

do i = 1, index
vec_a(i)= i**.5

vec_b(i)= (-1)*(i**2)

end do

res = dot_product(vec_a, vec_b)

write (*,*) vec_a, vec_b
write (*,*) res

end program vector2

! gfortran2 -o vector2 vector2.f95
! vector2 >text55.txt 2>text56.txt
//end source continue comment
, except making the inner product calculated externally. I have zero
chance of getting it correct, so I'll spare you the flailing attempt.
Screenshot here: http://zaxfuuq.net/c++5.jpg

To imitate it, I believe the appropriate c++ inner product would be
around negative 25.

You are not actually showing the fortran function that calculates the dot
product. That fortran source code simply populates 2 arrays of 4 elements
then calls the function dot_product(). It is the function dot_product you
want to code, but you aren't showing the souce for that.

In fortran ** is the power symbol, in C and C++ you can use the pow
function. Although some number raised to the power of 2 it's just as simple
to multiply the number by itself. Raising a number to the power of .5 is
taking the square root of it. So basically all that fortran code is filling
one array of 4 elements with the square roots of 1 to 4, the second 4
element array with the squares of 1 to 4, then calling the function
dot_product on them which returns a single number.

G

#### Gerry Ford

Jim Langston said:
Gerry Ford wrote:

You are not actually showing the fortran function that calculates the dot
product. That fortran source code simply populates 2 arrays of 4 elements
then calls the function dot_product(). It is the function dot_product you
want to code, but you aren't showing the souce for that.

In fortran ** is the power symbol, in C and C++ you can use the pow
function. Although some number raised to the power of 2 it's just as
simple to multiply the number by itself. Raising a number to the power of
.5 is taking the square root of it. So basically all that fortran code is
filling one array of 4 elements with the square roots of 1 to 4, the
second 4 element array with the squares of 1 to 4, then calling the
function dot_product on them which returns a single number.
You're prettymuch right on all this. I appreciate you talking through this
source for the benefit of those less familiar with my common C extension of
choice.

There isn't fortran code for dot_product, as it comes with the food over
there. That shocked the heck out of me the first time I realized it. I was
given to understand that c++ had likewise, but not to worry. With what we
have for headers, we can write it from scratch.

double float c++_dot_product (array vec_a , array vec_b, integer index)
{
// declare local vars
res = 0;
term=0;
sum=0;
for (i = 0; i < index; ++ i)
{
term=vec_a(i)*v_b(i);
sum = sum + term;

}
res = powl(sum, .5);

return res;
}

How does one correctly code the caller for this and the external function
itself?

J

#### Jim Langston

Gerry said:
You're prettymuch right on all this. I appreciate you talking
through this source for the benefit of those less familiar with my
common C extension of choice.

There isn't fortran code for dot_product, as it comes with the food
over there. That shocked the heck out of me the first time I
realized it. I was given to understand that c++ had likewise, but
not to worry. With what we have for headers, we can write it from
scratch.
double float c++_dot_product (array vec_a , array vec_b, integer
index) {
// declare local vars
res = 0;
term=0;
sum=0;
for (i = 0; i < index; ++ i)
{
term=vec_a(i)*v_b(i);
sum = sum + term;

}
res = powl(sum, .5);

return res;
}

How does one correctly code the caller for this and the external
function itself?

Output of the follow program is:
0
1
1.414213562373095
1.732050807568877
0
1
4
9
Dot Product: 4.716493561705802

#include <cmath>
#include <vector>
#include <iostream>

double dot_product (const std::vector<double>& vec_a, const
std::vector<double>& vec_b)
{
if ( vec_a.size() != vec_b.size() )
{
std::cerr << "Vectors for dot product are not same size!\n";
return 0.0;
}

double sum = 0;
for ( std::size_t i = 0; i < vec_a.size(); ++i )
{
sum += vec_a * vec_b;
}
return std: ow(sum, .5);
}

// Following prototype is not needed in this program since
// the definition is above, but would be used in another
// source file without the previous definition.
double dot_product (const std::vector<double>& vec_a, const
std::vector<double>& vec_b);

int main()
{
std::vector<double> vec_a;
std::vector<double> vec_b;

for ( int i = 0; i < 4; ++i )
{
vec_a.push_back( std::sqrt( static_cast<double>( i )) );
vec_b.push_back( i * i );
}

std::cout.precision(16);

std::copy(vec_a.begin(), vec_a.end(),
std: stream_iterator<double>(std::cout, "\n"));
std::copy(vec_b.begin(), vec_b.end(),
std: stream_iterator<double>(std::cout, "\n"));

std::cout << "Dot Product: " << dot_product(vec_a, vec_b) << "\n";
return 0;
}

An alternative to the static_cast<double>( i ) is chaning the for loop with
a double.

for ( double i = 0; i < 4.0; i += 1.0 )
{
vec_a.push_back( std::sqrt( i ) );
vec_b.push_back( i * i );
}

M

#### Michael DOUBEZ

Jim Langston a écrit :
Gerry said:
You're prettymuch right on all this. I appreciate you talking
through this source for the benefit of those less familiar with my
common C extension of choice.

There isn't fortran code for dot_product, as it comes with the food
over there. That shocked the heck out of me the first time I
realized it. I was given to understand that c++ had likewise, but
not to worry. With what we have for headers, we can write it from
scratch.
double float c++_dot_product (array vec_a , array vec_b, integer
index) {
// declare local vars
res = 0;
term=0;
sum=0;
for (i = 0; i < index; ++ i)
{
term=vec_a(i)*v_b(i);
sum = sum + term;

}
res = powl(sum, .5);

return res;
}

How does one correctly code the caller for this and the external
function itself?

Output of the follow program is:
0
1
1.414213562373095
1.732050807568877
0
1
4
9
Dot Product: 4.716493561705802

#include <cmath>
#include <vector>
#include <iostream>

double dot_product (const std::vector<double>& vec_a, const
std::vector<double>& vec_b)
{
if ( vec_a.size() != vec_b.size() )
{
std::cerr << "Vectors for dot product are not same size!\n";
return 0.0;
}

double sum = 0;
for ( std::size_t i = 0; i < vec_a.size(); ++i )
{
sum += vec_a * vec_b;
}
return std: ow(sum, .5);
}

// Following prototype is not needed in this program since
// the definition is above, but would be used in another
// source file without the previous definition.
double dot_product (const std::vector<double>& vec_a, const
std::vector<double>& vec_b);

int main()
{
std::vector<double> vec_a;
std::vector<double> vec_b;

for ( int i = 0; i < 4; ++i )
{
vec_a.push_back( std::sqrt( static_cast<double>( i )) );
vec_b.push_back( i * i );
}

std::cout.precision(16);

std::copy(vec_a.begin(), vec_a.end(),
std: stream_iterator<double>(std::cout, "\n"));
std::copy(vec_b.begin(), vec_b.end(),
std: stream_iterator<double>(std::cout, "\n"));

std::cout << "Dot Product: " << dot_product(vec_a, vec_b) << "\n";
return 0;
}

An alternative to the static_cast<double>( i ) is chaning the for loop with
a double.

for ( double i = 0; i < 4.0; i += 1.0 )
{
vec_a.push_back( std::sqrt( i ) );
vec_b.push_back( i * i );
}

In fact, in C++, the only version of std::sqrt() is double sqrt(double);
the other variants with float and long double are C99 additions. In the
standard case, the integer should be promoted to double and the
static_cast<double>() is not necessary.
for ( int i = 0; i < 4; ++i )
{
vec_a.push_back( std::sqrt( i ) );
vec_b.push_back( i * i );
}

I guess that in the case of C99 extension, an integer in parameter is
forwarded to the double flavor otherwise, there would be an ambiguity.

Michael

J

#### James Kanze

[...]
In fact, in C++, the only version of std::sqrt() is double
sqrt(double); the other variants with float and long double

Overloads for float and long have been present in C++ at least
since the 1998 version of the standard.
In the standard case, the integer should be promoted to double
and the static_cast<double>() is not necessary.
for ( int i = 0; i < 4; ++i )
{
vec_a.push_back( std::sqrt( i ) );
vec_b.push_back( i * i );
}
I guess that in the case of C99 extension, an integer in
parameter is forwarded to the double flavor otherwise, there
would be an ambiguity.

Why? I think that there will be an ambiguity if std::sqrt() is
called with an int. That's what the standard (and Sun CC) say,
anyway.

P

#### peter koch

I've been pecking away at writing a program that will calculate the inner
product of two double-width four-vectors.
Why? There are libraries that do this better than you or I could
reasonably hope to do unless we really took the time (and perhaps even
then! ;-)).
I am quite sure of that even if I don't really know what double-width
and four-vector is. These are neither terms of C++ nor of mathematics.
Larry thinks I'm well started with the following source to populate a
vector:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <math.h>

int main() {
std::vector<double> four_vector;

for (double i=0.0; i<4.0; i++)
four_vector.push_back(sqrt(i));
This loop is really dangerous. You risk having five elements in your
vector. Also it is inefficient as you (presumably!) know that there
should be four elements in the vector.
Use reserve or prefer a fixed-size vector which imo is the best
solution provided that you will always have a fixed number of elements
std::cout.precision(16);

std::copy(four_vector.begin(), four_vector.end(),
std: stream_iterator<double>(std::cout, "\n"));
return 0;

}

How do I imitate the following fortran source:
program vector2
implicit none
integer index, i
integer, parameter :: some_kind_number = selected_real_kind (p=16)
real (kind = some_kind_number), dimension(4):: vec_a, vec_b
real (kind = some_kind_number) :: res

index = 4

do i = 1, index
vec_a(i)= i**.5

vec_b(i)= (-1)*(i**2)
this would be something like

for (size_t i(0); i < 4; ++i)
{
a = sqrt(i);
b = -i*i;
}
end do

res = dot_product(vec_a, vec_b)

write (*,*) vec_a, vec_b
write (*,*) res

I can't imagine you having problems with the dot-product and I do not
understand the fortran output formats.
end program vector2

/Peter

G

#### Gerry Ford

Jim Langston said:
Gerry Ford wrote:

Thanks, Jim. In particular I appreciate the absence of disparaging remarks
concerning the god-awful syntax on my first function in c++ in a decade.
std::copy(vec_a.begin(), vec_a.end(),
std: stream_iterator<double>(std::cout, "\n"));
std::copy(vec_b.begin(), vec_b.end(),
std: stream_iterator<double>(std::cout, "\n"));

I've got 2 compilers that object to the above, to wit:
42 C:\Program Files\gfortran\fortran source\vector3.cpp `ostream_iterator'
is not a member of `std'
,with dev cpp and
vector3.cpp:52:12: warning: no newline at end of file
vector3.cpp: In function 'int main()':
vector3.cpp:42: error: 'ostream_iterator' is not a member of 'std'
vector3.cpp:42: error: expected primary-expression before 'double'
vector3.cpp:44: error: 'ostream_iterator' is not a member of 'std'
vector3.cpp:44: error: expected primary-expression before 'double'
with g++.

What gives?

G

#### Gerry Ford

I've been pecking away at writing a program that will calculate the inner
product of two double-width four-vectors.
Why? There are libraries that do this better than you or I could
reasonably hope to do unless we really took the time (and perhaps even
then! ;-)).
I am quite sure of that even if I don't really know what double-width
and four-vector is. These are neither terms of C++ nor of mathematics.

--->Do you know how to get these libraries hooked into a garden-variety
console app?

As to the rest, you sound german, so I'll address you so. Ein Vierervektor
soll etwa nicht in der Mathematik sein? Sie ercheinen im ersten Paragraph
in Einstein 1916 Mathematische Hilfsmittel fuer die Aufstellung allgemein
kovarianter Gleichungen.

Double width is twice the width of a float.

M

#### Michael DOUBEZ

James Kanze a écrit :
[...]
In fact, in C++, the only version of std::sqrt() is double
sqrt(double); the other variants with float and long double

Overloads for float and long have been present in C++ at least
since the 1998 version of the standard.

Funny thing. I really believed it was an extension.
Why? I think that there will be an ambiguity if std::sqrt() is
called with an int. That's what the standard (and Sun CC) say,
anyway.

I have found the 26.5-5 overload of cmath functions with float and long
double but where does the standard say it must trigger an ambiguity ?
Although it seems logical, wouldn't that break old C code making the
distinction between sqrt and sqrtf ?
I guess it is not that much a change.

Michael

R

#### Richard Herring

In message
Why? There are libraries that do this better than you or I could
reasonably hope to do unless we really took the time (and perhaps even
then! ;-)).
I am quite sure of that even if I don't really know what double-width
and four-vector is. These are neither terms of C++ nor of mathematics.

"Four-vector" is a standard term in relativistic physics.
This loop is really dangerous. You risk having five elements in your
vector.

With probability approaching zero. I doubt if there are _any_
floating-point implementations where a double can't exactly represent
all integers up to some value considerably larger than a 32-bit int, and
perform exact arithmetic on them. Even a float can count up to 4 without
error.
Also it is inefficient as you (presumably!) know that there
should be four elements in the vector.

_Measurably_ inefficient?
Use reserve

You really think it will help? The very first push_back will do
something internally equivalent to reserve(N) for some N which quite
likely exceeds 4.
or prefer a fixed-size vector which imo is the best
solution provided that you will always have a fixed number of elements

There may well be a good argument for having a dedicated class
representing four-vectors, but this isn't it.

J

#### James Kanze

Michael said:
James Kanze a ?crit :
[...]
In fact, in C++, the only version of std::sqrt() is double
sqrt(double); the other variants with float and long double
Overloads for float and long have been present in C++ at least
since the 1998 version of the standard.
Funny thing. I really believed it was an extension.
I have found the 26.5-5 overload of cmath functions with float
and long double but where does the standard say it must
trigger an ambiguity ?

Where does it say which one should be called? Basically, in §13.3.3.1.1, all of the standard conversions are
ranked, and int->float, int->double and int->long double all
have the same rank (conversion). Even in cases where int->float
is lossy.
Although it seems logical, wouldn't that break old C code
making the distinction between sqrt and sqrtf ?

Yep. There's no such thing as an ambiguous function call in C:
"sqrt( i )" calls "sqrt( double )", because that's the only
function named sqrt.

Ideally, only std::sqrt() is overloaded; and ::sqrt() continues
to behave as in C. (I'm not too sure what the standard
requires/allows in this respect.)

Note too that there is no std::sqrtf.

T

#### Thomas J. Gritzan

Gerry said:
Thanks, Jim. In particular I appreciate the absence of disparaging remarks
concerning the god-awful syntax on my first function in c++ in a decade.

I've got 2 compilers that object to the above, to wit:
42 C:\Program Files\gfortran\fortran source\vector3.cpp `ostream_iterator'
is not a member of `std'
,with dev cpp and
vector3.cpp:52:12: warning: no newline at end of file
vector3.cpp: In function 'int main()':
vector3.cpp:42: error: 'ostream_iterator' is not a member of 'std'
vector3.cpp:42: error: expected primary-expression before 'double'
vector3.cpp:44: error: 'ostream_iterator' is not a member of 'std'
vector3.cpp:44: error: expected primary-expression before 'double'
with g++.

What gives?

#include <iterator>

T

#### Thomas J. Gritzan

Gerry Ford schrieb:
[...]
There isn't fortran code for dot_product, as it comes with the food over
there. That shocked the heck out of me the first time I realized it. I was
given to understand that c++ had likewise, but not to worry. With what we
have for headers, we can write it from scratch.

double float c++_dot_product (array vec_a , array vec_b, integer index)
{
// declare local vars
res = 0;
term=0;
sum=0;
for (i = 0; i < index; ++ i)
{
term=vec_a(i)*v_b(i);
sum = sum + term;

}
res = powl(sum, .5);

return res;
}

How does one correctly code the caller for this and the external function
itself?

Two questions:
1) Why do you take the root from the result? A dot product is the sum of
the product of the elements.
2) Why don't you use std::inner_product?

#include <numeric>

double res = std::inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0.0);

P

#### peter koch

In message

"Four-vector" is a standard term in relativistic physics.

With probability approaching zero. I doubt if there are _any_
floating-point implementations where a double can't exactly represent
all integers up to some value considerably larger than a 32-bit int, and
perform exact arithmetic on them. Even a float can count up to 4 without
error.

I fully agree with you here. I saw a loop controled by a double and my
gut instinct told me that this was bad. Having integer increments make
this safe, of course so there is no reason to worry.
_Measurably_ inefficient?

You really think it will help? The very first push_back will do
something internally equivalent to reserve(N) for some N which quite
likely exceeds 4.

Perhaps. I have not examined my implementation but would expect it to
have reserves of 1, 2 and four.
There may well be a good argument for having a dedicated class
representing four-vectors, but this isn't it.

If all your four-vectors are dynamically allocated, I would expect new/
delete to easily dominate some types of computations - all depending
on how many temporaries you need, of course.

/Peter

P

#### peter koch

--->Do you know how to get these libraries hooked into a garden-variety
console app?

Hooked up? There are no specific stuff to do in order to hook up. Many
numerical applications probably are "garden-variety" console
applications.
As to the rest, you sound german, so I'll address you so.  Ein Vierervektor
soll etwa nicht in der Mathematik sein?  Sie ercheinen im ersten Paragraph
in Einstein 1916 Mathematische Hilfsmittel fuer die Aufstellung allgemein
kovarianter Gleichungen.

Double width is twice the width of a float.
I am not german and don't see how I sound as if I am? And actually, I
expected you to be american so this nationality guessing is not so
easy I presume.

J

#### James Kanze

On 19 Feb., 11:41, Richard Herring <[email protected][127.0.0.1]> wrote:

[...]
Perhaps. I have not examined my implementation but would expect it to
have reserves of 1, 2 and four.

Why? (That's certainly not what my implementation would do, if
I were writing it.)

P

#### peter koch

On 19 Feb., 11:41, Richard Herring <[email protected][127.0.0.1]> wrote:

[...]
Perhaps. I have not examined my implementation but would expect it to
have reserves of 1, 2 and four.

Why?  (That's certainly not what my implementation would do, if
I were writing it.)

Because I would expect std::vector to grow exponentially. Now, I know
that this does not mean doubling, but for very small numbers I would
expect an effective doubling.
I see behind the lines a suggestion that there might be a faster
growth for small values and this could well be so. Intuitively I
understood this not to be according to the standard, but this was pure
intuition.
Now looking at it, it looks as my implementation allocates four times
- namely as 1,2,3 and 4 elements. It tries to grow to
max(new_size,current_capacity + current_capacity/2).

/Peter

G

#### Gerry Ford

That's certainly what I wanted, not so much what I got.

I'll try that syntax and think I can pull it off externally.

--
Gerry Ford

"Er hat sich georgiert." Der Spiegel, 2008, sich auf Chimpy Eins komma null
beziehend.
Thomas J. Gritzan said:
Gerry Ford schrieb:
[...]
There isn't fortran code for dot_product, as it comes with the food over
there. That shocked the heck out of me the first time I realized it. I
was given to understand that c++ had likewise, but not to worry. With
what we have for headers, we can write it from scratch.

double float c++_dot_product (array vec_a , array vec_b, integer index)
{
// declare local vars
res = 0;
term=0;
sum=0;
for (i = 0; i < index; ++ i)
{
term=vec_a(i)*v_b(i);
sum = sum + term;

}
res = powl(sum, .5);

return res;
}

How does one correctly code the caller for this and the external function
itself?

Two questions:
1) Why do you take the root from the result? A dot product is the sum of
the product of the elements.
2) Why don't you use std::inner_product?

#include <numeric>

double res = std::inner_product(vec1.begin(), vec1.end(), vec2.begin(),
0.0);

--
Thomas
http://www.netmeister.org/news/learn2quote.html
An ideal world is left as an excercise to the reader.
--- Paul Graham, On Lisp 8.1