Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #91612 > unrolled thread
| Started by | db <dieterhansbritz@gmail.com> |
|---|---|
| First post | 2023-09-09 10:54 +0200 |
| Last post | 2023-09-11 05:14 -0700 |
| Articles | 13 on this page of 33 — 9 participants |
Back to article view | Back to comp.lang.c++
Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-09 10:54 +0200
Re: Problem with calling C++ from Fortran Muttley@dastardlyhq.com - 2023-09-09 09:02 +0000
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-09 12:47 +0200
Re: Problem with calling C++ from Fortran Muttley@dastardlyhq.com - 2023-09-09 10:51 +0000
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-09 12:52 +0200
Re: Problem with calling C++ from Fortran Muttley@dastardlyhq.com - 2023-09-09 11:00 +0000
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-10 14:33 +0200
Re: Problem with calling C++ from Fortran Paavo Helde <eesnimi@osa.pri.ee> - 2023-09-10 18:49 +0300
Re: Problem with calling C++ from Fortran Muttley@dastardlyhq.com - 2023-09-11 08:23 +0000
Re: Problem with calling C++ from Fortran Paavo Helde <eesnimi@osa.pri.ee> - 2023-09-09 16:56 +0300
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-10 14:36 +0200
Re: Problem with calling C++ from Fortran James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-11 00:14 -0400
Re: Problem with calling C++ from Fortran Bo Persson <bo@bo-persson.se> - 2023-09-10 16:08 +0200
Re: Problem with calling C++ from Fortran "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-09-09 16:30 +0200
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-10 14:48 +0200
Re: Problem with calling C++ from Fortran Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-10 14:22 +0100
Re: Problem with calling C++ from Fortran Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-10 17:27 +0100
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-11 14:00 +0200
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-11 05:21 -0700
Re: Problem with calling C++ from Fortran Muttley@dastardlyhq.com - 2023-09-11 13:33 +0000
Re: Problem with calling C++ from Fortran Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 00:26 +0100
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-12 10:48 +0200
Re: Problem with calling C++ from Fortran Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 14:14 +0100
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-12 07:15 -0700
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-12 02:00 -0700
Re: Problem with calling C++ from Fortran Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 14:22 +0100
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-12 07:32 -0700
Re: Problem with calling C++ from Fortran db <dieterhansbritz@gmail.com> - 2023-09-12 18:36 +0200
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-19 02:39 -0700
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-10 08:38 -0700
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-10 09:51 -0700
Re: Problem with calling C++ from Fortran Michael S <already5chosen@yahoo.com> - 2023-09-11 02:49 -0700
Buy Zen Mushroom Chocolate Bar Microdose "https://psychedelicminds.shop/" <psychedelicsmind@gmail.com> - 2023-09-11 05:14 -0700
Page 2 of 2 — ← Prev page 1 [2]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-12 00:26 +0100 |
| Message-ID | <87cyyoqoka.fsf@bsb.me.uk> |
| In reply to | #91683 |
db <dieterhansbritz@gmail.com> writes:
> On 10.09.2023 15.22, Ben Bacarisse wrote:
>> db <dieterhansbritz@gmail.com> writes:
>>
>>> On 09.09.2023 11.02, Muttley@dastardlyhq.com wrote:
>>>> On Sat, 9 Sep 2023 10:54:33 +0200
>>>> db <dieterhansbritz@gmail.com> wrote:
>>>>> but now it says that C-double doesn't exist.
>>>>>
>>>>> Any ideas?
>>>> C++ mangles function names so that the name you give the function isn't
>>>> the
>>>> name the dynamic loader sees in the binary. You need to put this around whatever
>>>> function you want to call from Fortran so it has C style linkage which means
>>>> the name remains the same:
>>>> extern "C" {
>>>> void calledFromFortran()
>>>> {
>>>> :
>>>> }
>>>> }
>>>>
>>> Where should this go in the code? I added it at the end as is,
>>> and now I get this:
>>>
>>> ~/ownlib90/tests> ./jbandtest
>>> jband.cpp:88:1: error: expected initializer before 'extern'
>>> 88 | extern "C" {
>>> | ^~~~~~
>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
>>> 96 | {
>>> | ^
>>> jband.cpp: In function 'void calledFromFortran()':
>>> jband.cpp:350:9: error: expected primary-expression before ':' token
>>> 350 | :
>>> ...
>> You are giving people very little to go on. There's an unknown command
>> (./jbandtest) the gives some errors where only one line of code can be
>> seen.
>> Can you produce a cut-down version to the program that shows the same
>> error -- mimimal example of the C++ and of the Fortran that should
>> calls it but which fails? That would mean you could post the code.
>> If that is not possible, can you link to the source so those who know
>> both C++ and Fortran can take a proper look?
>
> I put the C++ function here: www.dieterbritz.dk/jband.cpp
> After getting errors about the extern lines, whch I had
> added at the end, I shifted it to near the start:
>
> #include <iostream>
> #include <fstream>
> #include <iomanip>
> #include "math.h"
>
> using namespace std;
>
> extern "C" {
>
> void calledFromFortran()
> {
> :
> }
>
> }
Remove them all. You have two options. One: correct the C++. To do
this put this, and only this,
extern "C" {
const long double iband(const long double tbar);
}
just after the #include lines. This is perfect (the first const is a
meaningless word here and the compiler may warn you about that) but it
will do.
Next replace
#include "math.h"
with
#include <math.h>
I'd also remove the two unnecessary #include lines (for iomanip and
fstream). All of these are "tidying up". Only the extern "C" part I
gave corrects an actual mistake.
The second option is the turn the code in C which links directly with
Fortran. The only C++ used by the code is one "cout << " line (not a
good way to report an error, but that's not important right now) and a
setting for pi that is not a compile-time constant (4*atanl(1)) written
in a more fussy way.
To convert to C, copy the file to jband.c (rather than .cpp) and replce
the declaration for pi. Given the code is littered with explicit 21
digits decimals (a little more than the precision of C's usualy long
double type) I would just write
static const long double pi = 3.14159265358979323846L;
Now replace the cout line with
fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
This writes the message to the error stream and put only these two
include lines at the top:
#include <math.h>
#include <stdio.h>
Now the file is C code.
Frankly, this is the way I'd go, since linking C is just that bit
simpler than linking C++. But if the code is going to become fully
fledged (and complex) C++, obviously use my first option.
> I still get errors pertaining to these lines. But after adding
> the -c to the two compilation lines in the script, these are
> now the only errors. I think I am getting closer. The errors
> are now
Yes, you must compile it like this:
g++ -c jband.cpp (for C++ code)
gcc -c jband.c (for C code)
You don't need any -o but you could add in lots of warnings like
gcc -Wall -Wextra -c jband.c
> jband.cpp: In function 'void calledFromFortran()':
> jband.cpp:12:9: error: expected primary-expression before ':' token
> 12 | :
> | ^
> jband.cpp: At global scope:
> jband.cpp:96:1: error: expected initializer before 'extern'
> 96 | extern "C" {
> | ^~~~~~
> jband.cpp:104:1: error: expected unqualified-id before '{' token
> 104 | {
> | ^
> jbandtest.f90:28:14:
>
> 28 | FORTJBAND = JBAND (tbar)
> | 1
> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
>
> The last error will go away together with the others.
Michael S has given you one way to go for that. My comments were going
to be more general. You have several ways of specifying the types, and
I could not tell if you really wanted all of them. In general, I would
define the Fortran types from the C ones (since those are the types you
need for the call and return) and leave it at that.
But the big one is that the Fortran code seems to think the function is
called jband, when in fact it's called iband.
I went for this:
module STUFF
use iso_c_binding
integer, parameter :: qud=real(c_long_double)
end module STUFF
program JBAND_TEST
use STUFF; implicit none
real(qud) :: tbar, curr, FORTJBAND
do
read *, tbar
if (tbar < 0) exit
curr = FORTJBAND (tbar)
print '(" curr =", f10.4)', curr
enddo
end program JBAND_TEST
function FORTJBAND (tbar)
use STUFF; implicit none
interface
function IBAND (tbar) bind(c)
use STUFF
real(qud), VALUE :: tbar
real(qud) :: IBAND
end function iband
end interface
real(qud) :: FORTJBAND, tbar
FORTJBAND = IBAND(tbar)
end function FORTJBAND
Note that you can compile the Fortran along with the C at the same time
if you like:
$ gfortran -o jtest jbandtest.f90 jband.c -lm
$ ./jtest
1
curr = 1.5224
1e-10
curr =56419.9584
-1
$
($ is my Linux command-line prompt). I have no idea if these are
correct results and I can't be sure what you need to run on your system,
but the code links and appears to work.
If you go with the C++ option, the linking needs the standard C++
library:
$ gfortran -o jtest jbandtest.f90 jband.cpp -lstdc++ -lm
$ ./jtest
1
curr = 1.5224
1e-10
curr =56419.9584
-1
$
BTW, you said the C++ was written by a C++ expert. I don't think it
was!
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | db <dieterhansbritz@gmail.com> |
|---|---|
| Date | 2023-09-12 10:48 +0200 |
| Message-ID | <udp8l4$1frsv$1@dont-email.me> |
| In reply to | #91693 |
On 12.09.2023 01.26, Ben Bacarisse wrote:
> db <dieterhansbritz@gmail.com> writes:
>
>> On 10.09.2023 15.22, Ben Bacarisse wrote:
>>> db <dieterhansbritz@gmail.com> writes:
>>>
>>>> On 09.09.2023 11.02, Muttley@dastardlyhq.com wrote:
>>>>> On Sat, 9 Sep 2023 10:54:33 +0200
>>>>> db <dieterhansbritz@gmail.com> wrote:
>>>>>> but now it says that C-double doesn't exist.
>>>>>>
>>>>>> Any ideas?
>>>>> C++ mangles function names so that the name you give the function isn't
>>>>> the
>>>>> name the dynamic loader sees in the binary. You need to put this around whatever
>>>>> function you want to call from Fortran so it has C style linkage which means
>>>>> the name remains the same:
>>>>> extern "C" {
>>>>> void calledFromFortran()
>>>>> {
>>>>> :
>>>>> }
>>>>> }
>>>>>
>>>> Where should this go in the code? I added it at the end as is,
>>>> and now I get this:
>>>>
>>>> ~/ownlib90/tests> ./jbandtest
>>>> jband.cpp:88:1: error: expected initializer before 'extern'
>>>> 88 | extern "C" {
>>>> | ^~~~~~
>>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
>>>> 96 | {
>>>> | ^
>>>> jband.cpp: In function 'void calledFromFortran()':
>>>> jband.cpp:350:9: error: expected primary-expression before ':' token
>>>> 350 | :
>>>> ...
>>> You are giving people very little to go on. There's an unknown command
>>> (./jbandtest) the gives some errors where only one line of code can be
>>> seen.
>>> Can you produce a cut-down version to the program that shows the same
>>> error -- mimimal example of the C++ and of the Fortran that should
>>> calls it but which fails? That would mean you could post the code.
>>> If that is not possible, can you link to the source so those who know
>>> both C++ and Fortran can take a proper look?
>>
>> I put the C++ function here: www.dieterbritz.dk/jband.cpp
>> After getting errors about the extern lines, whch I had
>> added at the end, I shifted it to near the start:
>>
>> #include <iostream>
>> #include <fstream>
>> #include <iomanip>
>> #include "math.h"
>>
>> using namespace std;
>>
>> extern "C" {
>>
>> void calledFromFortran()
>> {
>> :
>> }
>>
>> }
>
> Remove them all. You have two options. One: correct the C++. To do
> this put this, and only this,
>
> extern "C" {
> const long double iband(const long double tbar);
> }
>
> just after the #include lines. This is perfect (the first const is a
> meaningless word here and the compiler may warn you about that) but it
> will do.
>
> Next replace
>
> #include "math.h"
>
> with
>
> #include <math.h>
>
> I'd also remove the two unnecessary #include lines (for iomanip and
> fstream). All of these are "tidying up". Only the extern "C" part I
> gave corrects an actual mistake.
>
> The second option is the turn the code in C which links directly with
> Fortran. The only C++ used by the code is one "cout << " line (not a
> good way to report an error, but that's not important right now) and a
> setting for pi that is not a compile-time constant (4*atanl(1)) written
> in a more fussy way.
>
> To convert to C, copy the file to jband.c (rather than .cpp) and replce
> the declaration for pi. Given the code is littered with explicit 21
> digits decimals (a little more than the precision of C's usualy long
> double type) I would just write
>
> static const long double pi = 3.14159265358979323846L;
>
> Now replace the cout line with
>
> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
>
> This writes the message to the error stream and put only these two
> include lines at the top:
>
> #include <math.h>
> #include <stdio.h>
>
> Now the file is C code.
>
> Frankly, this is the way I'd go, since linking C is just that bit
> simpler than linking C++. But if the code is going to become fully
> fledged (and complex) C++, obviously use my first option.
>
>> I still get errors pertaining to these lines. But after adding
>> the -c to the two compilation lines in the script, these are
>> now the only errors. I think I am getting closer. The errors
>> are now
>
> Yes, you must compile it like this:
>
> g++ -c jband.cpp (for C++ code)
> gcc -c jband.c (for C code)
>
> You don't need any -o but you could add in lots of warnings like
>
> gcc -Wall -Wextra -c jband.c
>
>> jband.cpp: In function 'void calledFromFortran()':
>> jband.cpp:12:9: error: expected primary-expression before ':' token
>> 12 | :
>> | ^
>> jband.cpp: At global scope:
>> jband.cpp:96:1: error: expected initializer before 'extern'
>> 96 | extern "C" {
>> | ^~~~~~
>> jband.cpp:104:1: error: expected unqualified-id before '{' token
>> 104 | {
>> | ^
>> jbandtest.f90:28:14:
>>
>> 28 | FORTJBAND = JBAND (tbar)
>> | 1
>> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
>>
>> The last error will go away together with the others.
>
> Michael S has given you one way to go for that. My comments were going
> to be more general. You have several ways of specifying the types, and
> I could not tell if you really wanted all of them. In general, I would
> define the Fortran types from the C ones (since those are the types you
> need for the call and return) and leave it at that.
>
> But the big one is that the Fortran code seems to think the function is
> called jband, when in fact it's called iband.
>
> I went for this:
>
> module STUFF
> use iso_c_binding
> integer, parameter :: qud=real(c_long_double)
> end module STUFF
> program JBAND_TEST
> use STUFF; implicit none
> real(qud) :: tbar, curr, FORTJBAND
> do
> read *, tbar
> if (tbar < 0) exit
> curr = FORTJBAND (tbar)
> print '(" curr =", f10.4)', curr
> enddo
> end program JBAND_TEST
>
> function FORTJBAND (tbar)
> use STUFF; implicit none
> interface
> function IBAND (tbar) bind(c)
> use STUFF
> real(qud), VALUE :: tbar
> real(qud) :: IBAND
> end function iband
> end interface
> real(qud) :: FORTJBAND, tbar
> FORTJBAND = IBAND(tbar)
> end function FORTJBAND
>
> Note that you can compile the Fortran along with the C at the same time
> if you like:
>
> $ gfortran -o jtest jbandtest.f90 jband.c -lm
> $ ./jtest
> 1
> curr = 1.5224
> 1e-10
> curr =56419.9584
> -1
> $
>
> ($ is my Linux command-line prompt). I have no idea if these are
> correct results and I can't be sure what you need to run on your system,
> but the code links and appears to work.
>
> If you go with the C++ option, the linking needs the standard C++
> library:
>
> $ gfortran -o jtest jbandtest.f90 jband.cpp -lstdc++ -lm
> $ ./jtest
> 1
> curr = 1.5224
> 1e-10
> curr =56419.9584
> -1
> $
>
> BTW, you said the C++ was written by a C++ expert. I don't think it
> was!
>
The code, apart from the extra lines suggested by someone here,
but without the information on where to put them, is runnable
C++ code written by another person who knows C++ very well. I
myself use Fortran and you are right, I know next to nothing
about C++. I did use the extra code exactly as is, but possibly
put it in the wrong place. I tried two, without success.
I am giving up, and will translate the C++ function into Fortran,
where I know what I'm doing.
--
Dieter Britz
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-12 14:14 +0100 |
| Message-ID | <87cyynpm90.fsf@bsb.me.uk> |
| In reply to | #91697 |
db <dieterhansbritz@gmail.com> writes: >> BTW, you said the C++ was written by a C++ expert. I don't think it >> was! >> > The code, apart from the extra lines suggested by someone here, > but without the information on where to put them, is runnable > C++ code written by another person who knows C++ very well. I was just saying that the code does not look like it was written by someone who knows C++ very well. All those unnecessary duplicated sizes. A const qualified function return type. Including "math.h" rather that either <math.h> or <cmath>. > I myself use Fortran and you are right, I know next to nothing about > C++. Did I say that? Sorry. > I did use the extra code exactly as is, but possibly > put it in the wrong place. I tried two, without success. > I am giving up, and will translate the C++ function into Fortran, > where I know what I'm doing. OK. Odd to give up just as two people have given you working code. Oh well... Mind you, the C++ (or C) just picks an array and an initial value (an 'x' in a polynomial evaluation) and calculates a simple sum. It will be trivial in Fortran. The hard work is in the coefficients and those can just be coped. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-12 07:15 -0700 |
| Message-ID | <ac4c9220-8eb6-41d7-a5ad-522e33c55d28n@googlegroups.com> |
| In reply to | #91697 |
On Tuesday, September 12, 2023 at 11:48:55 AM UTC+3, db wrote:
> On 12.09.2023 01.26, Ben Bacarisse wrote:
> > db <dieterh...@gmail.com> writes:
> >
> >> On 10.09.2023 15.22, Ben Bacarisse wrote:
> >>> db <dieterh...@gmail.com> writes:
> >>>
> >>>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
> >>>>> On Sat, 9 Sep 2023 10:54:33 +0200
> >>>>> db <dieterh...@gmail.com> wrote:
> >>>>>> but now it says that C-double doesn't exist.
> >>>>>>
> >>>>>> Any ideas?
> >>>>> C++ mangles function names so that the name you give the function isn't
> >>>>> the
> >>>>> name the dynamic loader sees in the binary. You need to put this around whatever
> >>>>> function you want to call from Fortran so it has C style linkage which means
> >>>>> the name remains the same:
> >>>>> extern "C" {
> >>>>> void calledFromFortran()
> >>>>> {
> >>>>> :
> >>>>> }
> >>>>> }
> >>>>>
> >>>> Where should this go in the code? I added it at the end as is,
> >>>> and now I get this:
> >>>>
> >>>> ~/ownlib90/tests> ./jbandtest
> >>>> jband.cpp:88:1: error: expected initializer before 'extern'
> >>>> 88 | extern "C" {
> >>>> | ^~~~~~
> >>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
> >>>> 96 | {
> >>>> | ^
> >>>> jband.cpp: In function 'void calledFromFortran()':
> >>>> jband.cpp:350:9: error: expected primary-expression before ':' token
> >>>> 350 | :
> >>>> ...
> >>> You are giving people very little to go on. There's an unknown command
> >>> (./jbandtest) the gives some errors where only one line of code can be
> >>> seen.
> >>> Can you produce a cut-down version to the program that shows the same
> >>> error -- mimimal example of the C++ and of the Fortran that should
> >>> calls it but which fails? That would mean you could post the code.
> >>> If that is not possible, can you link to the source so those who know
> >>> both C++ and Fortran can take a proper look?
> >>
> >> I put the C++ function here: www.dieterbritz.dk/jband.cpp
> >> After getting errors about the extern lines, whch I had
> >> added at the end, I shifted it to near the start:
> >>
> >> #include <iostream>
> >> #include <fstream>
> >> #include <iomanip>
> >> #include "math.h"
> >>
> >> using namespace std;
> >>
> >> extern "C" {
> >>
> >> void calledFromFortran()
> >> {
> >> :
> >> }
> >>
> >> }
> >
> > Remove them all. You have two options. One: correct the C++. To do
> > this put this, and only this,
> >
> > extern "C" {
> > const long double iband(const long double tbar);
> > }
> >
> > just after the #include lines. This is perfect (the first const is a
> > meaningless word here and the compiler may warn you about that) but it
> > will do.
> >
> > Next replace
> >
> > #include "math.h"
> >
> > with
> >
> > #include <math.h>
> >
> > I'd also remove the two unnecessary #include lines (for iomanip and
> > fstream). All of these are "tidying up". Only the extern "C" part I
> > gave corrects an actual mistake.
> >
> > The second option is the turn the code in C which links directly with
> > Fortran. The only C++ used by the code is one "cout << " line (not a
> > good way to report an error, but that's not important right now) and a
> > setting for pi that is not a compile-time constant (4*atanl(1)) written
> > in a more fussy way.
> >
> > To convert to C, copy the file to jband.c (rather than .cpp) and replce
> > the declaration for pi. Given the code is littered with explicit 21
> > digits decimals (a little more than the precision of C's usualy long
> > double type) I would just write
> >
> > static const long double pi = 3.14159265358979323846L;
> >
> > Now replace the cout line with
> >
> > fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
> >
> > This writes the message to the error stream and put only these two
> > include lines at the top:
> >
> > #include <math.h>
> > #include <stdio.h>
> >
> > Now the file is C code.
> >
> > Frankly, this is the way I'd go, since linking C is just that bit
> > simpler than linking C++. But if the code is going to become fully
> > fledged (and complex) C++, obviously use my first option.
> >
> >> I still get errors pertaining to these lines. But after adding
> >> the -c to the two compilation lines in the script, these are
> >> now the only errors. I think I am getting closer. The errors
> >> are now
> >
> > Yes, you must compile it like this:
> >
> > g++ -c jband.cpp (for C++ code)
> > gcc -c jband.c (for C code)
> >
> > You don't need any -o but you could add in lots of warnings like
> >
> > gcc -Wall -Wextra -c jband.c
> >
> >> jband.cpp: In function 'void calledFromFortran()':
> >> jband.cpp:12:9: error: expected primary-expression before ':' token
> >> 12 | :
> >> | ^
> >> jband.cpp: At global scope:
> >> jband.cpp:96:1: error: expected initializer before 'extern'
> >> 96 | extern "C" {
> >> | ^~~~~~
> >> jband.cpp:104:1: error: expected unqualified-id before '{' token
> >> 104 | {
> >> | ^
> >> jbandtest.f90:28:14:
> >>
> >> 28 | FORTJBAND = JBAND (tbar)
> >> | 1
> >> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
> >>
> >> The last error will go away together with the others.
> >
> > Michael S has given you one way to go for that. My comments were going
> > to be more general. You have several ways of specifying the types, and
> > I could not tell if you really wanted all of them. In general, I would
> > define the Fortran types from the C ones (since those are the types you
> > need for the call and return) and leave it at that.
> >
> > But the big one is that the Fortran code seems to think the function is
> > called jband, when in fact it's called iband.
> >
> > I went for this:
> >
> > module STUFF
> > use iso_c_binding
> > integer, parameter :: qud=real(c_long_double)
> > end module STUFF
> > program JBAND_TEST
> > use STUFF; implicit none
> > real(qud) :: tbar, curr, FORTJBAND
> > do
> > read *, tbar
> > if (tbar < 0) exit
> > curr = FORTJBAND (tbar)
> > print '(" curr =", f10.4)', curr
> > enddo
> > end program JBAND_TEST
> >
> > function FORTJBAND (tbar)
> > use STUFF; implicit none
> > interface
> > function IBAND (tbar) bind(c)
> > use STUFF
> > real(qud), VALUE :: tbar
> > real(qud) :: IBAND
> > end function iband
> > end interface
> > real(qud) :: FORTJBAND, tbar
> > FORTJBAND = IBAND(tbar)
> > end function FORTJBAND
> >
> > Note that you can compile the Fortran along with the C at the same time
> > if you like:
> >
> > $ gfortran -o jtest jbandtest.f90 jband.c -lm
> > $ ./jtest
> > 1
> > curr = 1.5224
> > 1e-10
> > curr =56419.9584
> > -1
> > $
> >
> > ($ is my Linux command-line prompt). I have no idea if these are
> > correct results and I can't be sure what you need to run on your system,
> > but the code links and appears to work.
> >
> > If you go with the C++ option, the linking needs the standard C++
> > library:
> >
> > $ gfortran -o jtest jbandtest.f90 jband.cpp -lstdc++ -lm
> > $ ./jtest
> > 1
> > curr = 1.5224
> > 1e-10
> > curr =56419.9584
> > -1
> > $
> >
> > BTW, you said the C++ was written by a C++ expert. I don't think it
> > was!
> >
> The code, apart from the extra lines suggested by someone here,
> but without the information on where to put them, is runnable
> C++ code written by another person who knows C++ very well. I
> myself use Fortran and you are right, I know next to nothing
> about C++. I did use the extra code exactly as is, but possibly
> put it in the wrong place. I tried two, without success.
> I am giving up,
It seems to me, you are giving up too early.
If I guessed you original code correctly then all you have to do
on C++ side is to replace that line:
const long double iband(const long double tbar)
by that line:
extern "C" long double iband(const long double tbar)
> and will translate the C++ function into Fortran,
> where I know what I'm doing.
Understanding what you are doing is valuable, yes.
> --
> Dieter Britz
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-12 02:00 -0700 |
| Message-ID | <2ccb965a-8d31-48af-97ad-2d96daa4862dn@googlegroups.com> |
| In reply to | #91693 |
On Tuesday, September 12, 2023 at 2:26:49 AM UTC+3, Ben Bacarisse wrote:
> db <dieterh...@gmail.com> writes:
>
> > On 10.09.2023 15.22, Ben Bacarisse wrote:
> >> db <dieterh...@gmail.com> writes:
> >>
> >>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
> >>>> On Sat, 9 Sep 2023 10:54:33 +0200
> >>>> db <dieterh...@gmail.com> wrote:
> >>>>> but now it says that C-double doesn't exist.
> >>>>>
> >>>>> Any ideas?
> >>>> C++ mangles function names so that the name you give the function isn't
> >>>> the
> >>>> name the dynamic loader sees in the binary. You need to put this around whatever
> >>>> function you want to call from Fortran so it has C style linkage which means
> >>>> the name remains the same:
> >>>> extern "C" {
> >>>> void calledFromFortran()
> >>>> {
> >>>> :
> >>>> }
> >>>> }
> >>>>
> >>> Where should this go in the code? I added it at the end as is,
> >>> and now I get this:
> >>>
> >>> ~/ownlib90/tests> ./jbandtest
> >>> jband.cpp:88:1: error: expected initializer before 'extern'
> >>> 88 | extern "C" {
> >>> | ^~~~~~
> >>> jband.cpp:96:1: error: expected unqualified-id before '{' token
> >>> 96 | {
> >>> | ^
> >>> jband.cpp: In function 'void calledFromFortran()':
> >>> jband.cpp:350:9: error: expected primary-expression before ':' token
> >>> 350 | :
> >>> ...
> >> You are giving people very little to go on. There's an unknown command
> >> (./jbandtest) the gives some errors where only one line of code can be
> >> seen.
> >> Can you produce a cut-down version to the program that shows the same
> >> error -- mimimal example of the C++ and of the Fortran that should
> >> calls it but which fails? That would mean you could post the code.
> >> If that is not possible, can you link to the source so those who know
> >> both C++ and Fortran can take a proper look?
> >
> > I put the C++ function here: www.dieterbritz.dk/jband.cpp
> > After getting errors about the extern lines, whch I had
> > added at the end, I shifted it to near the start:
> >
> > #include <iostream>
> > #include <fstream>
> > #include <iomanip>
> > #include "math.h"
> >
> > using namespace std;
> >
> > extern "C" {
> >
> > void calledFromFortran()
> > {
> > :
> > }
> >
> > }
> Remove them all. You have two options. One: correct the C++. To do
> this put this, and only this,
>
> extern "C" {
> const long double iband(const long double tbar);
> }
>
> just after the #include lines. This is perfect (the first const is a
> meaningless word here and the compiler may warn you about that) but it
> will do.
>
> Next replace
>
> #include "math.h"
>
> with
>
> #include <math.h>
>
> I'd also remove the two unnecessary #include lines (for iomanip and
> fstream). All of these are "tidying up". Only the extern "C" part I
> gave corrects an actual mistake.
>
> The second option is the turn the code in C which links directly with
> Fortran. The only C++ used by the code is one "cout << " line (not a
> good way to report an error, but that's not important right now) and a
> setting for pi that is not a compile-time constant (4*atanl(1)) written
> in a more fussy way.
>
> To convert to C, copy the file to jband.c (rather than .cpp) and replce
> the declaration for pi. Given the code is littered with explicit 21
> digits decimals (a little more than the precision of C's usualy long
> double type) I would just write
>
> static const long double pi = 3.14159265358979323846L;
>
> Now replace the cout line with
>
> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
>
> This writes the message to the error stream and put only these two
> include lines at the top:
>
> #include <math.h>
> #include <stdio.h>
>
> Now the file is C code.
>
> Frankly, this is the way I'd go, since linking C is just that bit
> simpler than linking C++. But if the code is going to become fully
> fledged (and complex) C++, obviously use my first option.
> > I still get errors pertaining to these lines. But after adding
> > the -c to the two compilation lines in the script, these are
> > now the only errors. I think I am getting closer. The errors
> > are now
> Yes, you must compile it like this:
>
> g++ -c jband.cpp (for C++ code)
> gcc -c jband.c (for C code)
>
> You don't need any -o but you could add in lots of warnings like
>
> gcc -Wall -Wextra -c jband.c
> > jband.cpp: In function 'void calledFromFortran()':
> > jband.cpp:12:9: error: expected primary-expression before ':' token
> > 12 | :
> > | ^
> > jband.cpp: At global scope:
> > jband.cpp:96:1: error: expected initializer before 'extern'
> > 96 | extern "C" {
> > | ^~~~~~
> > jband.cpp:104:1: error: expected unqualified-id before '{' token
> > 104 | {
> > | ^
> > jbandtest.f90:28:14:
> >
> > 28 | FORTJBAND = JBAND (tbar)
> > | 1
> > Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
> >
> > The last error will go away together with the others.
> Michael S has given you one way to go for that. My comments were going
> to be more general. You have several ways of specifying the types, and
> I could not tell if you really wanted all of them. In general, I would
> define the Fortran types from the C ones (since those are the types you
> need for the call and return) and leave it at that.
>
> But the big one is that the Fortran code seems to think the function is
> called jband, when in fact it's called iband.
>
> I went for this:
>
> module STUFF
> use iso_c_binding
> integer, parameter :: qud=real(c_long_double)
> end module STUFF
> program JBAND_TEST
> use STUFF; implicit none
> real(qud) :: tbar, curr, FORTJBAND
> do
> read *, tbar
> if (tbar < 0) exit
> curr = FORTJBAND (tbar)
> print '(" curr =", f10.4)', curr
> enddo
> end program JBAND_TEST
>
> function FORTJBAND (tbar)
> use STUFF; implicit none
> interface
> function IBAND (tbar) bind(c)
> use STUFF
> real(qud), VALUE :: tbar
> real(qud) :: IBAND
> end function iband
> end interface
I think, you are taking chances here. Even if it happens to work
on x86-64 Linux, it can fail on some other target where calling
conventions for long double return value in 'C' differ from those
of Fortran. The method shown in one of my previous posts
appear more robust:
interface
real(c_long_double) function IBAND (tbar) bind(c)
import c_long_double
real(c_long_double), value :: tbar
end function IBAND
> real(qud) :: FORTJBAND, tbar
> FORTJBAND = IBAND(tbar)
> end function FORTJBAND
>
> Note that you can compile the Fortran along with the C at the same time
> if you like:
>
> $ gfortran -o jtest jbandtest.f90 jband.c -lm
> $ ./jtest
> 1
> curr = 1.5224
> 1e-10
> curr =56419.9584
> -1
> $
>
> ($ is my Linux command-line prompt). I have no idea if these are
> correct results and I can't be sure what you need to run on your system,
> but the code links and appears to work.
>
> If you go with the C++ option, the linking needs the standard C++
> library:
>
> $ gfortran -o jtest jbandtest.f90 jband.cpp -lstdc++ -lm
> $ ./jtest
> 1
> curr = 1.5224
> 1e-10
> curr =56419.9584
> -1
> $
>
> BTW, you said the C++ was written by a C++ expert. I don't think it
> was!
With no relationships to C, C++ or Fortran, I don't like the way they evaluate
their polynomials from numerical perspective . But I assume that algorithm
was copied 'as is' from 40 y.o. book so it's not a fault of C++ programmer.
Despite my disliking, their method is good enough to achieve their modest
specified goal for relative accuracy: of 14-15 significant digits.
With smarter method the same or better accuracy can be achieved using
standard 'double" arithmetic (IEEE-754 binary64) thus making the routine
portable to platforms that have no support for extended precision math.
>
> --
> Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-12 14:22 +0100 |
| Message-ID | <87a5trplua.fsf@bsb.me.uk> |
| In reply to | #91698 |
Michael S <already5chosen@yahoo.com> writes:
> On Tuesday, September 12, 2023 at 2:26:49 AM UTC+3, Ben Bacarisse wrote:
>> db <dieterh...@gmail.com> writes:
>>
>> > On 10.09.2023 15.22, Ben Bacarisse wrote:
>> >> db <dieterh...@gmail.com> writes:
>> >>
>> >>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
>> >>>> On Sat, 9 Sep 2023 10:54:33 +0200
>> >>>> db <dieterh...@gmail.com> wrote:
>> >>>>> but now it says that C-double doesn't exist.
>> >>>>>
>> >>>>> Any ideas?
>> >>>> C++ mangles function names so that the name you give the function isn't
>> >>>> the
>> >>>> name the dynamic loader sees in the binary. You need to put this around whatever
>> >>>> function you want to call from Fortran so it has C style linkage which means
>> >>>> the name remains the same:
>> >>>> extern "C" {
>> >>>> void calledFromFortran()
>> >>>> {
>> >>>> :
>> >>>> }
>> >>>> }
>> >>>>
>> >>> Where should this go in the code? I added it at the end as is,
>> >>> and now I get this:
>> >>>
>> >>> ~/ownlib90/tests> ./jbandtest
>> >>> jband.cpp:88:1: error: expected initializer before 'extern'
>> >>> 88 | extern "C" {
>> >>> | ^~~~~~
>> >>> jband.cpp:96:1: error: expected unqualified-id before '{' token
>> >>> 96 | {
>> >>> | ^
>> >>> jband.cpp: In function 'void calledFromFortran()':
>> >>> jband.cpp:350:9: error: expected primary-expression before ':' token
>> >>> 350 | :
>> >>> ...
>> >> You are giving people very little to go on. There's an unknown command
>> >> (./jbandtest) the gives some errors where only one line of code can be
>> >> seen.
>> >> Can you produce a cut-down version to the program that shows the same
>> >> error -- mimimal example of the C++ and of the Fortran that should
>> >> calls it but which fails? That would mean you could post the code.
>> >> If that is not possible, can you link to the source so those who know
>> >> both C++ and Fortran can take a proper look?
>> >
>> > I put the C++ function here: www.dieterbritz.dk/jband.cpp
>> > After getting errors about the extern lines, whch I had
>> > added at the end, I shifted it to near the start:
>> >
>> > #include <iostream>
>> > #include <fstream>
>> > #include <iomanip>
>> > #include "math.h"
>> >
>> > using namespace std;
>> >
>> > extern "C" {
>> >
>> > void calledFromFortran()
>> > {
>> > :
>> > }
>> >
>> > }
>> Remove them all. You have two options. One: correct the C++. To do
>> this put this, and only this,
>>
>> extern "C" {
>> const long double iband(const long double tbar);
>> }
>>
>> just after the #include lines. This is perfect (the first const is a
>> meaningless word here and the compiler may warn you about that) but it
>> will do.
>>
>> Next replace
>>
>> #include "math.h"
>>
>> with
>>
>> #include <math.h>
>>
>> I'd also remove the two unnecessary #include lines (for iomanip and
>> fstream). All of these are "tidying up". Only the extern "C" part I
>> gave corrects an actual mistake.
>>
>> The second option is the turn the code in C which links directly with
>> Fortran. The only C++ used by the code is one "cout << " line (not a
>> good way to report an error, but that's not important right now) and a
>> setting for pi that is not a compile-time constant (4*atanl(1)) written
>> in a more fussy way.
>>
>> To convert to C, copy the file to jband.c (rather than .cpp) and replce
>> the declaration for pi. Given the code is littered with explicit 21
>> digits decimals (a little more than the precision of C's usualy long
>> double type) I would just write
>>
>> static const long double pi = 3.14159265358979323846L;
>>
>> Now replace the cout line with
>>
>> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
>>
>> This writes the message to the error stream and put only these two
>> include lines at the top:
>>
>> #include <math.h>
>> #include <stdio.h>
>>
>> Now the file is C code.
>>
>> Frankly, this is the way I'd go, since linking C is just that bit
>> simpler than linking C++. But if the code is going to become fully
>> fledged (and complex) C++, obviously use my first option.
>> > I still get errors pertaining to these lines. But after adding
>> > the -c to the two compilation lines in the script, these are
>> > now the only errors. I think I am getting closer. The errors
>> > are now
>> Yes, you must compile it like this:
>>
>> g++ -c jband.cpp (for C++ code)
>> gcc -c jband.c (for C code)
>>
>> You don't need any -o but you could add in lots of warnings like
>>
>> gcc -Wall -Wextra -c jband.c
>> > jband.cpp: In function 'void calledFromFortran()':
>> > jband.cpp:12:9: error: expected primary-expression before ':' token
>> > 12 | :
>> > | ^
>> > jband.cpp: At global scope:
>> > jband.cpp:96:1: error: expected initializer before 'extern'
>> > 96 | extern "C" {
>> > | ^~~~~~
>> > jband.cpp:104:1: error: expected unqualified-id before '{' token
>> > 104 | {
>> > | ^
>> > jbandtest.f90:28:14:
>> >
>> > 28 | FORTJBAND = JBAND (tbar)
>> > | 1
>> > Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
>> >
>> > The last error will go away together with the others.
>> Michael S has given you one way to go for that. My comments were going
>> to be more general. You have several ways of specifying the types, and
>> I could not tell if you really wanted all of them. In general, I would
>> define the Fortran types from the C ones (since those are the types you
>> need for the call and return) and leave it at that.
>>
>> But the big one is that the Fortran code seems to think the function is
>> called jband, when in fact it's called iband.
>>
>> I went for this:
>>
>> module STUFF
>> use iso_c_binding
>> integer, parameter :: qud=real(c_long_double)
>> end module STUFF
>> program JBAND_TEST
>> use STUFF; implicit none
>> real(qud) :: tbar, curr, FORTJBAND
>> do
>> read *, tbar
>> if (tbar < 0) exit
>> curr = FORTJBAND (tbar)
>> print '(" curr =", f10.4)', curr
>> enddo
>> end program JBAND_TEST
>>
>> function FORTJBAND (tbar)
>> use STUFF; implicit none
>> interface
>> function IBAND (tbar) bind(c)
>> use STUFF
>> real(qud), VALUE :: tbar
>> real(qud) :: IBAND
>> end function iband
>> end interface
>
> I think, you are taking chances here. Even if it happens to work
> on x86-64 Linux, it can fail on some other target where calling
> conventions for long double return value in 'C' differ from those
> of Fortran. The method shown in one of my previous posts
> appear more robust:
>
> interface
> real(c_long_double) function IBAND (tbar) bind(c)
> import c_long_double
> real(c_long_double), value :: tbar
> end function IBAND
I think I see -- keep the C-related types in the smallest interface? I
didn't study your example, but the OP renamed the C function and gave
the resulting Fortran function a native Fortran type. Is that what you
advise?
The OP should have taken your Fortran and applied my C++ edits. Maybe
they took my Fortran and it did not work on Windows. That would be a
shame.
>> BTW, you said the C++ was written by a C++ expert. I don't think it
>> was!
>
> With no relationships to C, C++ or Fortran, I don't like the way they
> evaluate their polynomials from numerical perspective . But I assume
> that algorithm was copied 'as is' from 40 y.o. book so it's not a
> fault of C++ programmer.
I was just remarking on the C++ itself which has some 'non-expert'
attributes.
> Despite my disliking, their method is good enough to achieve their modest
> specified goal for relative accuracy: of 14-15 significant digits.
> With smarter method the same or better accuracy can be achieved using
> standard 'double" arithmetic (IEEE-754 binary64) thus making the routine
> portable to platforms that have no support for extended precision
> math.
Interesting. I don't know the function being evaluated at all.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-12 07:32 -0700 |
| Message-ID | <f1b6f8e1-fa16-4fb7-b4b2-883788d098fdn@googlegroups.com> |
| In reply to | #91701 |
On Tuesday, September 12, 2023 at 4:23:09 PM UTC+3, Ben Bacarisse wrote:
> Michael S <already...@yahoo.com> writes:
>
> > On Tuesday, September 12, 2023 at 2:26:49 AM UTC+3, Ben Bacarisse wrote:
> >> db <dieterh...@gmail.com> writes:
> >>
> >> > On 10.09.2023 15.22, Ben Bacarisse wrote:
> >> >> db <dieterh...@gmail.com> writes:
> >> >>
> >> >>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
> >> >>>> On Sat, 9 Sep 2023 10:54:33 +0200
> >> >>>> db <dieterh...@gmail.com> wrote:
> >> >>>>> but now it says that C-double doesn't exist.
> >> >>>>>
> >> >>>>> Any ideas?
> >> >>>> C++ mangles function names so that the name you give the function isn't
> >> >>>> the
> >> >>>> name the dynamic loader sees in the binary. You need to put this around whatever
> >> >>>> function you want to call from Fortran so it has C style linkage which means
> >> >>>> the name remains the same:
> >> >>>> extern "C" {
> >> >>>> void calledFromFortran()
> >> >>>> {
> >> >>>> :
> >> >>>> }
> >> >>>> }
> >> >>>>
> >> >>> Where should this go in the code? I added it at the end as is,
> >> >>> and now I get this:
> >> >>>
> >> >>> ~/ownlib90/tests> ./jbandtest
> >> >>> jband.cpp:88:1: error: expected initializer before 'extern'
> >> >>> 88 | extern "C" {
> >> >>> | ^~~~~~
> >> >>> jband.cpp:96:1: error: expected unqualified-id before '{' token
> >> >>> 96 | {
> >> >>> | ^
> >> >>> jband.cpp: In function 'void calledFromFortran()':
> >> >>> jband.cpp:350:9: error: expected primary-expression before ':' token
> >> >>> 350 | :
> >> >>> ...
> >> >> You are giving people very little to go on. There's an unknown command
> >> >> (./jbandtest) the gives some errors where only one line of code can be
> >> >> seen.
> >> >> Can you produce a cut-down version to the program that shows the same
> >> >> error -- mimimal example of the C++ and of the Fortran that should
> >> >> calls it but which fails? That would mean you could post the code.
> >> >> If that is not possible, can you link to the source so those who know
> >> >> both C++ and Fortran can take a proper look?
> >> >
> >> > I put the C++ function here: www.dieterbritz.dk/jband.cpp
> >> > After getting errors about the extern lines, whch I had
> >> > added at the end, I shifted it to near the start:
> >> >
> >> > #include <iostream>
> >> > #include <fstream>
> >> > #include <iomanip>
> >> > #include "math.h"
> >> >
> >> > using namespace std;
> >> >
> >> > extern "C" {
> >> >
> >> > void calledFromFortran()
> >> > {
> >> > :
> >> > }
> >> >
> >> > }
> >> Remove them all. You have two options. One: correct the C++. To do
> >> this put this, and only this,
> >>
> >> extern "C" {
> >> const long double iband(const long double tbar);
> >> }
> >>
> >> just after the #include lines. This is perfect (the first const is a
> >> meaningless word here and the compiler may warn you about that) but it
> >> will do.
> >>
> >> Next replace
> >>
> >> #include "math.h"
> >>
> >> with
> >>
> >> #include <math.h>
> >>
> >> I'd also remove the two unnecessary #include lines (for iomanip and
> >> fstream). All of these are "tidying up". Only the extern "C" part I
> >> gave corrects an actual mistake.
> >>
> >> The second option is the turn the code in C which links directly with
> >> Fortran. The only C++ used by the code is one "cout << " line (not a
> >> good way to report an error, but that's not important right now) and a
> >> setting for pi that is not a compile-time constant (4*atanl(1)) written
> >> in a more fussy way.
> >>
> >> To convert to C, copy the file to jband.c (rather than .cpp) and replce
> >> the declaration for pi. Given the code is littered with explicit 21
> >> digits decimals (a little more than the precision of C's usualy long
> >> double type) I would just write
> >>
> >> static const long double pi = 3.14159265358979323846L;
> >>
> >> Now replace the cout line with
> >>
> >> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
> >>
> >> This writes the message to the error stream and put only these two
> >> include lines at the top:
> >>
> >> #include <math.h>
> >> #include <stdio.h>
> >>
> >> Now the file is C code.
> >>
> >> Frankly, this is the way I'd go, since linking C is just that bit
> >> simpler than linking C++. But if the code is going to become fully
> >> fledged (and complex) C++, obviously use my first option.
> >> > I still get errors pertaining to these lines. But after adding
> >> > the -c to the two compilation lines in the script, these are
> >> > now the only errors. I think I am getting closer. The errors
> >> > are now
> >> Yes, you must compile it like this:
> >>
> >> g++ -c jband.cpp (for C++ code)
> >> gcc -c jband.c (for C code)
> >>
> >> You don't need any -o but you could add in lots of warnings like
> >>
> >> gcc -Wall -Wextra -c jband.c
> >> > jband.cpp: In function 'void calledFromFortran()':
> >> > jband.cpp:12:9: error: expected primary-expression before ':' token
> >> > 12 | :
> >> > | ^
> >> > jband.cpp: At global scope:
> >> > jband.cpp:96:1: error: expected initializer before 'extern'
> >> > 96 | extern "C" {
> >> > | ^~~~~~
> >> > jband.cpp:104:1: error: expected unqualified-id before '{' token
> >> > 104 | {
> >> > | ^
> >> > jbandtest.f90:28:14:
> >> >
> >> > 28 | FORTJBAND = JBAND (tbar)
> >> > | 1
> >> > Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
> >> >
> >> > The last error will go away together with the others.
> >> Michael S has given you one way to go for that. My comments were going
> >> to be more general. You have several ways of specifying the types, and
> >> I could not tell if you really wanted all of them. In general, I would
> >> define the Fortran types from the C ones (since those are the types you
> >> need for the call and return) and leave it at that.
> >>
> >> But the big one is that the Fortran code seems to think the function is
> >> called jband, when in fact it's called iband.
> >>
> >> I went for this:
> >>
> >> module STUFF
> >> use iso_c_binding
> >> integer, parameter :: qud=real(c_long_double)
> >> end module STUFF
> >> program JBAND_TEST
> >> use STUFF; implicit none
> >> real(qud) :: tbar, curr, FORTJBAND
> >> do
> >> read *, tbar
> >> if (tbar < 0) exit
> >> curr = FORTJBAND (tbar)
> >> print '(" curr =", f10.4)', curr
> >> enddo
> >> end program JBAND_TEST
> >>
> >> function FORTJBAND (tbar)
> >> use STUFF; implicit none
> >> interface
> >> function IBAND (tbar) bind(c)
> >> use STUFF
> >> real(qud), VALUE :: tbar
> >> real(qud) :: IBAND
> >> end function iband
> >> end interface
> >
> > I think, you are taking chances here. Even if it happens to work
> > on x86-64 Linux, it can fail on some other target where calling
> > conventions for long double return value in 'C' differ from those
> > of Fortran. The method shown in one of my previous posts
> > appear more robust:
> >
> > interface
> > real(c_long_double) function IBAND (tbar) bind(c)
> > import c_long_double
> > real(c_long_double), value :: tbar
> > end function IBAND
> I think I see -- keep the C-related types in the smallest interface? I
> didn't study your example, but the OP renamed the C function and gave
> the resulting Fortran function a native Fortran type. Is that what you
> advise?
>
> The OP should have taken your Fortran and applied my C++ edits. Maybe
> they took my Fortran and it did not work on Windows. That would be a
> shame.
> >> BTW, you said the C++ was written by a C++ expert. I don't think it
> >> was!
> >
> > With no relationships to C, C++ or Fortran, I don't like the way they
> > evaluate their polynomials from numerical perspective . But I assume
> > that algorithm was copied 'as is' from 40 y.o. book so it's not a
> > fault of C++ programmer.
> I was just remarking on the C++ itself which has some 'non-expert'
> attributes.
> > Despite my disliking, their method is good enough to achieve their modest
> > specified goal for relative accuracy: of 14-15 significant digits.
> > With smarter method the same or better accuracy can be achieved using
> > standard 'double" arithmetic (IEEE-754 binary64) thus making the routine
> > portable to platforms that have no support for extended precision
> > math.
> Interesting. I don't know the function being evaluated at all.
>
I don't know it either. But I had drawn the graphs and looked at
coefficients in two ranges where precision is worst: [0.0081: 0.0158] and
[0.0158:0.0631].
A simple affine transform of the polynomial could either improve precision
of result by 4 orders of magnitude or reduce needs for precision of arithmetic
by 3 orders of magnitude while still somewhat improving the precision of result.
I'd guess, more advanced techniques can improve it further in both dimensions,
but low hanging fruits first.
> --
> Ben.
[toc] | [prev] | [next] | [standalone]
| From | db <dieterhansbritz@gmail.com> |
|---|---|
| Date | 2023-09-12 18:36 +0200 |
| Message-ID | <udq41s$1kto4$1@dont-email.me> |
| In reply to | #91703 |
On 12.09.2023 16.32, Michael S wrote:
> On Tuesday, September 12, 2023 at 4:23:09 PM UTC+3, Ben Bacarisse wrote:
>> Michael S <already...@yahoo.com> writes:
>>
>>> On Tuesday, September 12, 2023 at 2:26:49 AM UTC+3, Ben Bacarisse wrote:
>>>> db <dieterh...@gmail.com> writes:
>>>>
>>>>> On 10.09.2023 15.22, Ben Bacarisse wrote:
>>>>>> db <dieterh...@gmail.com> writes:
>>>>>>
>>>>>>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
>>>>>>>> On Sat, 9 Sep 2023 10:54:33 +0200
>>>>>>>> db <dieterh...@gmail.com> wrote:
>>>>>>>>> but now it says that C-double doesn't exist.
>>>>>>>>>
>>>>>>>>> Any ideas?
>>>>>>>> C++ mangles function names so that the name you give the function isn't
>>>>>>>> the
>>>>>>>> name the dynamic loader sees in the binary. You need to put this around whatever
>>>>>>>> function you want to call from Fortran so it has C style linkage which means
>>>>>>>> the name remains the same:
>>>>>>>> extern "C" {
>>>>>>>> void calledFromFortran()
>>>>>>>> {
>>>>>>>> :
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>> Where should this go in the code? I added it at the end as is,
>>>>>>> and now I get this:
>>>>>>>
>>>>>>> ~/ownlib90/tests> ./jbandtest
>>>>>>> jband.cpp:88:1: error: expected initializer before 'extern'
>>>>>>> 88 | extern "C" {
>>>>>>> | ^~~~~~
>>>>>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
>>>>>>> 96 | {
>>>>>>> | ^
>>>>>>> jband.cpp: In function 'void calledFromFortran()':
>>>>>>> jband.cpp:350:9: error: expected primary-expression before ':' token
>>>>>>> 350 | :
>>>>>>> ...
>>>>>> You are giving people very little to go on. There's an unknown command
>>>>>> (./jbandtest) the gives some errors where only one line of code can be
>>>>>> seen.
>>>>>> Can you produce a cut-down version to the program that shows the same
>>>>>> error -- mimimal example of the C++ and of the Fortran that should
>>>>>> calls it but which fails? That would mean you could post the code.
>>>>>> If that is not possible, can you link to the source so those who know
>>>>>> both C++ and Fortran can take a proper look?
>>>>>
>>>>> I put the C++ function here: www.dieterbritz.dk/jband.cpp
>>>>> After getting errors about the extern lines, whch I had
>>>>> added at the end, I shifted it to near the start:
>>>>>
>>>>> #include <iostream>
>>>>> #include <fstream>
>>>>> #include <iomanip>
>>>>> #include "math.h"
>>>>>
>>>>> using namespace std;
>>>>>
>>>>> extern "C" {
>>>>>
>>>>> void calledFromFortran()
>>>>> {
>>>>> :
>>>>> }
>>>>>
>>>>> }
>>>> Remove them all. You have two options. One: correct the C++. To do
>>>> this put this, and only this,
>>>>
>>>> extern "C" {
>>>> const long double iband(const long double tbar);
>>>> }
>>>>
>>>> just after the #include lines. This is perfect (the first const is a
>>>> meaningless word here and the compiler may warn you about that) but it
>>>> will do.
>>>>
>>>> Next replace
>>>>
>>>> #include "math.h"
>>>>
>>>> with
>>>>
>>>> #include <math.h>
>>>>
>>>> I'd also remove the two unnecessary #include lines (for iomanip and
>>>> fstream). All of these are "tidying up". Only the extern "C" part I
>>>> gave corrects an actual mistake.
>>>>
>>>> The second option is the turn the code in C which links directly with
>>>> Fortran. The only C++ used by the code is one "cout << " line (not a
>>>> good way to report an error, but that's not important right now) and a
>>>> setting for pi that is not a compile-time constant (4*atanl(1)) written
>>>> in a more fussy way.
>>>>
>>>> To convert to C, copy the file to jband.c (rather than .cpp) and replce
>>>> the declaration for pi. Given the code is littered with explicit 21
>>>> digits decimals (a little more than the precision of C's usualy long
>>>> double type) I would just write
>>>>
>>>> static const long double pi = 3.14159265358979323846L;
>>>>
>>>> Now replace the cout line with
>>>>
>>>> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
>>>>
>>>> This writes the message to the error stream and put only these two
>>>> include lines at the top:
>>>>
>>>> #include <math.h>
>>>> #include <stdio.h>
>>>>
>>>> Now the file is C code.
>>>>
>>>> Frankly, this is the way I'd go, since linking C is just that bit
>>>> simpler than linking C++. But if the code is going to become fully
>>>> fledged (and complex) C++, obviously use my first option.
>>>>> I still get errors pertaining to these lines. But after adding
>>>>> the -c to the two compilation lines in the script, these are
>>>>> now the only errors. I think I am getting closer. The errors
>>>>> are now
>>>> Yes, you must compile it like this:
>>>>
>>>> g++ -c jband.cpp (for C++ code)
>>>> gcc -c jband.c (for C code)
>>>>
>>>> You don't need any -o but you could add in lots of warnings like
>>>>
>>>> gcc -Wall -Wextra -c jband.c
>>>>> jband.cpp: In function 'void calledFromFortran()':
>>>>> jband.cpp:12:9: error: expected primary-expression before ':' token
>>>>> 12 | :
>>>>> | ^
>>>>> jband.cpp: At global scope:
>>>>> jband.cpp:96:1: error: expected initializer before 'extern'
>>>>> 96 | extern "C" {
>>>>> | ^~~~~~
>>>>> jband.cpp:104:1: error: expected unqualified-id before '{' token
>>>>> 104 | {
>>>>> | ^
>>>>> jbandtest.f90:28:14:
>>>>>
>>>>> 28 | FORTJBAND = JBAND (tbar)
>>>>> | 1
>>>>> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
>>>>>
>>>>> The last error will go away together with the others.
>>>> Michael S has given you one way to go for that. My comments were going
>>>> to be more general. You have several ways of specifying the types, and
>>>> I could not tell if you really wanted all of them. In general, I would
>>>> define the Fortran types from the C ones (since those are the types you
>>>> need for the call and return) and leave it at that.
>>>>
>>>> But the big one is that the Fortran code seems to think the function is
>>>> called jband, when in fact it's called iband.
>>>>
>>>> I went for this:
>>>>
>>>> module STUFF
>>>> use iso_c_binding
>>>> integer, parameter :: qud=real(c_long_double)
>>>> end module STUFF
>>>> program JBAND_TEST
>>>> use STUFF; implicit none
>>>> real(qud) :: tbar, curr, FORTJBAND
>>>> do
>>>> read *, tbar
>>>> if (tbar < 0) exit
>>>> curr = FORTJBAND (tbar)
>>>> print '(" curr =", f10.4)', curr
>>>> enddo
>>>> end program JBAND_TEST
>>>>
>>>> function FORTJBAND (tbar)
>>>> use STUFF; implicit none
>>>> interface
>>>> function IBAND (tbar) bind(c)
>>>> use STUFF
>>>> real(qud), VALUE :: tbar
>>>> real(qud) :: IBAND
>>>> end function iband
>>>> end interface
>>>
>>> I think, you are taking chances here. Even if it happens to work
>>> on x86-64 Linux, it can fail on some other target where calling
>>> conventions for long double return value in 'C' differ from those
>>> of Fortran. The method shown in one of my previous posts
>>> appear more robust:
>>>
>>> interface
>>> real(c_long_double) function IBAND (tbar) bind(c)
>>> import c_long_double
>>> real(c_long_double), value :: tbar
>>> end function IBAND
>> I think I see -- keep the C-related types in the smallest interface? I
>> didn't study your example, but the OP renamed the C function and gave
>> the resulting Fortran function a native Fortran type. Is that what you
>> advise?
>>
>> The OP should have taken your Fortran and applied my C++ edits. Maybe
>> they took my Fortran and it did not work on Windows. That would be a
>> shame.
>>>> BTW, you said the C++ was written by a C++ expert. I don't think it
>>>> was!
>>>
>>> With no relationships to C, C++ or Fortran, I don't like the way they
>>> evaluate their polynomials from numerical perspective . But I assume
>>> that algorithm was copied 'as is' from 40 y.o. book so it's not a
>>> fault of C++ programmer.
>> I was just remarking on the C++ itself which has some 'non-expert'
>> attributes.
>>> Despite my disliking, their method is good enough to achieve their modest
>>> specified goal for relative accuracy: of 14-15 significant digits.
>>> With smarter method the same or better accuracy can be achieved using
>>> standard 'double" arithmetic (IEEE-754 binary64) thus making the routine
>>> portable to platforms that have no support for extended precision
>>> math.
>> Interesting. I don't know the function being evaluated at all.
>>
>
> I don't know it either. But I had drawn the graphs and looked at
> coefficients in two ranges where precision is worst: [0.0081: 0.0158] and
> [0.0158:0.0631].
> A simple affine transform of the polynomial could either improve precision
> of result by 4 orders of magnitude or reduce needs for precision of arithmetic
> by 3 orders of magnitude while still somewhat improving the precision of result.
> I'd guess, more advanced techniques can improve it further in both dimensions,
> but low hanging fruits first.
>
>> --
>> Ben.
The person who gave me the C++ code is an older experienced C++
programmer. Maybe he uses out of data C++ features but the
function works as is (without the extra lines given to me here,
which were meant to help with calling it from Fortran). He also
gave me a little C++ program to call it, and it produced
output that I was able to verify.
The problem is electrochemical, the current vs time at a flat band
electrode flush with an insulating plane, for which there is no
analytical solution, and the function gives highly accurate values
using piecewise polynomial fits. Actually, he is over the top with
the accuracy because in practice, comparing with experiments, 3-4
figures are all that we need but he likes to do the best that can
be done.
--
Dieter Britz
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-19 02:39 -0700 |
| Message-ID | <9f0bc74c-6243-4a8f-9539-cbecc304df15n@googlegroups.com> |
| In reply to | #91704 |
On Tuesday, September 12, 2023 at 7:36:32 PM UTC+3, db wrote:
> On 12.09.2023 16.32, Michael S wrote:
> > On Tuesday, September 12, 2023 at 4:23:09 PM UTC+3, Ben Bacarisse wrote:
> >> Michael S <already...@yahoo.com> writes:
> >>
> >>> On Tuesday, September 12, 2023 at 2:26:49 AM UTC+3, Ben Bacarisse wrote:
> >>>> db <dieterh...@gmail.com> writes:
> >>>>
> >>>>> On 10.09.2023 15.22, Ben Bacarisse wrote:
> >>>>>> db <dieterh...@gmail.com> writes:
> >>>>>>
> >>>>>>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
> >>>>>>>> On Sat, 9 Sep 2023 10:54:33 +0200
> >>>>>>>> db <dieterh...@gmail.com> wrote:
> >>>>>>>>> but now it says that C-double doesn't exist.
> >>>>>>>>>
> >>>>>>>>> Any ideas?
> >>>>>>>> C++ mangles function names so that the name you give the function isn't
> >>>>>>>> the
> >>>>>>>> name the dynamic loader sees in the binary. You need to put this around whatever
> >>>>>>>> function you want to call from Fortran so it has C style linkage which means
> >>>>>>>> the name remains the same:
> >>>>>>>> extern "C" {
> >>>>>>>> void calledFromFortran()
> >>>>>>>> {
> >>>>>>>> :
> >>>>>>>> }
> >>>>>>>> }
> >>>>>>>>
> >>>>>>> Where should this go in the code? I added it at the end as is,
> >>>>>>> and now I get this:
> >>>>>>>
> >>>>>>> ~/ownlib90/tests> ./jbandtest
> >>>>>>> jband.cpp:88:1: error: expected initializer before 'extern'
> >>>>>>> 88 | extern "C" {
> >>>>>>> | ^~~~~~
> >>>>>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
> >>>>>>> 96 | {
> >>>>>>> | ^
> >>>>>>> jband.cpp: In function 'void calledFromFortran()':
> >>>>>>> jband.cpp:350:9: error: expected primary-expression before ':' token
> >>>>>>> 350 | :
> >>>>>>> ...
> >>>>>> You are giving people very little to go on. There's an unknown command
> >>>>>> (./jbandtest) the gives some errors where only one line of code can be
> >>>>>> seen.
> >>>>>> Can you produce a cut-down version to the program that shows the same
> >>>>>> error -- mimimal example of the C++ and of the Fortran that should
> >>>>>> calls it but which fails? That would mean you could post the code.
> >>>>>> If that is not possible, can you link to the source so those who know
> >>>>>> both C++ and Fortran can take a proper look?
> >>>>>
> >>>>> I put the C++ function here: www.dieterbritz.dk/jband.cpp
> >>>>> After getting errors about the extern lines, whch I had
> >>>>> added at the end, I shifted it to near the start:
> >>>>>
> >>>>> #include <iostream>
> >>>>> #include <fstream>
> >>>>> #include <iomanip>
> >>>>> #include "math.h"
> >>>>>
> >>>>> using namespace std;
> >>>>>
> >>>>> extern "C" {
> >>>>>
> >>>>> void calledFromFortran()
> >>>>> {
> >>>>> :
> >>>>> }
> >>>>>
> >>>>> }
> >>>> Remove them all. You have two options. One: correct the C++. To do
> >>>> this put this, and only this,
> >>>>
> >>>> extern "C" {
> >>>> const long double iband(const long double tbar);
> >>>> }
> >>>>
> >>>> just after the #include lines. This is perfect (the first const is a
> >>>> meaningless word here and the compiler may warn you about that) but it
> >>>> will do.
> >>>>
> >>>> Next replace
> >>>>
> >>>> #include "math.h"
> >>>>
> >>>> with
> >>>>
> >>>> #include <math.h>
> >>>>
> >>>> I'd also remove the two unnecessary #include lines (for iomanip and
> >>>> fstream). All of these are "tidying up". Only the extern "C" part I
> >>>> gave corrects an actual mistake.
> >>>>
> >>>> The second option is the turn the code in C which links directly with
> >>>> Fortran. The only C++ used by the code is one "cout << " line (not a
> >>>> good way to report an error, but that's not important right now) and a
> >>>> setting for pi that is not a compile-time constant (4*atanl(1)) written
> >>>> in a more fussy way.
> >>>>
> >>>> To convert to C, copy the file to jband.c (rather than .cpp) and replce
> >>>> the declaration for pi. Given the code is littered with explicit 21
> >>>> digits decimals (a little more than the precision of C's usualy long
> >>>> double type) I would just write
> >>>>
> >>>> static const long double pi = 3.14159265358979323846L;
> >>>>
> >>>> Now replace the cout line with
> >>>>
> >>>> fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
> >>>>
> >>>> This writes the message to the error stream and put only these two
> >>>> include lines at the top:
> >>>>
> >>>> #include <math.h>
> >>>> #include <stdio.h>
> >>>>
> >>>> Now the file is C code.
> >>>>
> >>>> Frankly, this is the way I'd go, since linking C is just that bit
> >>>> simpler than linking C++. But if the code is going to become fully
> >>>> fledged (and complex) C++, obviously use my first option.
> >>>>> I still get errors pertaining to these lines. But after adding
> >>>>> the -c to the two compilation lines in the script, these are
> >>>>> now the only errors. I think I am getting closer. The errors
> >>>>> are now
> >>>> Yes, you must compile it like this:
> >>>>
> >>>> g++ -c jband.cpp (for C++ code)
> >>>> gcc -c jband.c (for C code)
> >>>>
> >>>> You don't need any -o but you could add in lots of warnings like
> >>>>
> >>>> gcc -Wall -Wextra -c jband.c
> >>>>> jband.cpp: In function 'void calledFromFortran()':
> >>>>> jband.cpp:12:9: error: expected primary-expression before ':' token
> >>>>> 12 | :
> >>>>> | ^
> >>>>> jband.cpp: At global scope:
> >>>>> jband.cpp:96:1: error: expected initializer before 'extern'
> >>>>> 96 | extern "C" {
> >>>>> | ^~~~~~
> >>>>> jband.cpp:104:1: error: expected unqualified-id before '{' token
> >>>>> 104 | {
> >>>>> | ^
> >>>>> jbandtest.f90:28:14:
> >>>>>
> >>>>> 28 | FORTJBAND = JBAND (tbar)
> >>>>> | 1
> >>>>> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
> >>>>>
> >>>>> The last error will go away together with the others.
> >>>> Michael S has given you one way to go for that. My comments were going
> >>>> to be more general. You have several ways of specifying the types, and
> >>>> I could not tell if you really wanted all of them. In general, I would
> >>>> define the Fortran types from the C ones (since those are the types you
> >>>> need for the call and return) and leave it at that.
> >>>>
> >>>> But the big one is that the Fortran code seems to think the function is
> >>>> called jband, when in fact it's called iband.
> >>>>
> >>>> I went for this:
> >>>>
> >>>> module STUFF
> >>>> use iso_c_binding
> >>>> integer, parameter :: qud=real(c_long_double)
> >>>> end module STUFF
> >>>> program JBAND_TEST
> >>>> use STUFF; implicit none
> >>>> real(qud) :: tbar, curr, FORTJBAND
> >>>> do
> >>>> read *, tbar
> >>>> if (tbar < 0) exit
> >>>> curr = FORTJBAND (tbar)
> >>>> print '(" curr =", f10.4)', curr
> >>>> enddo
> >>>> end program JBAND_TEST
> >>>>
> >>>> function FORTJBAND (tbar)
> >>>> use STUFF; implicit none
> >>>> interface
> >>>> function IBAND (tbar) bind(c)
> >>>> use STUFF
> >>>> real(qud), VALUE :: tbar
> >>>> real(qud) :: IBAND
> >>>> end function iband
> >>>> end interface
> >>>
> >>> I think, you are taking chances here. Even if it happens to work
> >>> on x86-64 Linux, it can fail on some other target where calling
> >>> conventions for long double return value in 'C' differ from those
> >>> of Fortran. The method shown in one of my previous posts
> >>> appear more robust:
> >>>
> >>> interface
> >>> real(c_long_double) function IBAND (tbar) bind(c)
> >>> import c_long_double
> >>> real(c_long_double), value :: tbar
> >>> end function IBAND
> >> I think I see -- keep the C-related types in the smallest interface? I
> >> didn't study your example, but the OP renamed the C function and gave
> >> the resulting Fortran function a native Fortran type. Is that what you
> >> advise?
> >>
> >> The OP should have taken your Fortran and applied my C++ edits. Maybe
> >> they took my Fortran and it did not work on Windows. That would be a
> >> shame.
> >>>> BTW, you said the C++ was written by a C++ expert. I don't think it
> >>>> was!
> >>>
> >>> With no relationships to C, C++ or Fortran, I don't like the way they
> >>> evaluate their polynomials from numerical perspective . But I assume
> >>> that algorithm was copied 'as is' from 40 y.o. book so it's not a
> >>> fault of C++ programmer.
> >> I was just remarking on the C++ itself which has some 'non-expert'
> >> attributes.
> >>> Despite my disliking, their method is good enough to achieve their modest
> >>> specified goal for relative accuracy: of 14-15 significant digits.
> >>> With smarter method the same or better accuracy can be achieved using
> >>> standard 'double" arithmetic (IEEE-754 binary64) thus making the routine
> >>> portable to platforms that have no support for extended precision
> >>> math.
> >> Interesting. I don't know the function being evaluated at all.
> >>
> >
> > I don't know it either. But I had drawn the graphs and looked at
> > coefficients in two ranges where precision is worst: [0.0081: 0.0158] and
> > [0.0158:0.0631].
> > A simple affine transform of the polynomial could either improve precision
> > of result by 4 orders of magnitude or reduce needs for precision of arithmetic
> > by 3 orders of magnitude while still somewhat improving the precision of result.
> > I'd guess, more advanced techniques can improve it further in both dimensions,
> > but low hanging fruits first.
> >
> >> --
> >> Ben.
> The person who gave me the C++ code is an older experienced C++
> programmer. Maybe he uses out of data C++ features but the
> function works as is (without the extra lines given to me here,
> which were meant to help with calling it from Fortran). He also
> gave me a little C++ program to call it, and it produced
> output that I was able to verify.
>
> The problem is electrochemical, the current vs time at a flat band
> electrode flush with an insulating plane, for which there is no
> analytical solution, and the function gives highly accurate values
> using piecewise polynomial fits. Actually, he is over the top with
> the accuracy because in practice, comparing with experiments, 3-4
> figures are all that we need but he likes to do the best that can
> be done.
>
> --
> Dieter Britz
If all you need is 3-4 significant figures then you can use much simpler
calculation. Like that (pay attention, it's C rather than C++).
#include <math.h>
#include <stdio.h>
static double polyval(const double coef[], int order, double x);
double iband(double tbar)
{
if (tbar <= 0) {
printf("\nError in stredges::iband(): tbar must be > 0");
return 0;
}
// Coefficients of the polynomial approximation for tbar < 0.76
static const double c1[] = {
-2.0610398523438721606087449e-01,
+3.8436669168692465117185331e-01,
-2.0618169531912929413418346e-01,
-2.6474292774634270832496992e-02,
+3.1131226184858380642960328e-03,
+5.6415965971931841142037414e-01,
};
const int c1_order = sizeof(c1)/sizeof(c1[0])-1;
if (tbar < 0.76)
return polyval(c1, c1_order, tbar)/sqrt(tbar) + 1;
// Coefficients of the polynomial approximation for tbar >= 0.76
static const double c2[] = {
+1.3247948853085559402034700e+01,
-2.8936433794424133211569633e+01,
+2.2857148655763359956491203e+01,
-5.3743813763778698859386414e+00,
-3.5789894047006239277645653e+00,
+6.2827953597648754628587263e+00,
};
const int c2_order = sizeof(c2)/sizeof(c2[0])-1;
static const double c2_b2 = 3.00445175355660613529;
static const double c2_b1 = 1.93;
double log_t = log(tbar);
return polyval(c2, c2_order, 1/(log_t+c2_b1))/(log_t+c2_b2);
}
static double polyval(const double coef[], int order, double x)
{
double sum = coef[0];
for (int i = 0; i < order; ++i)
sum = sum * x + coef[i+1];
return sum;
}
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-10 08:38 -0700 |
| Message-ID | <0765ca71-5d8b-4f0f-9287-f3de55271ac1n@googlegroups.com> |
| In reply to | #91612 |
On Saturday, September 9, 2023 at 11:54:53 AM UTC+3, db wrote:
> I want to call a C++ function from Fortran. The function is
> called jband, in the file jband.cpp. The function is of type
> long double, and so is its argument tbar.
> I wrote this:
>
> module STUFF
> integer, parameter :: dbl=selected_real_kind(14)
> integer, parameter :: qud=selected_real_kind(30)
> end module STUFF
> program JBAND_TEST
> use STUFF; implicit none
> real(dbl) :: curr, FORTJBAND
> real(qud) :: tbar
> do
> read *, tbar
> if (tbar < 0) exit
> curr = FORTJBAND (tbar)
> print '(" curr =", f10.4)', curr
> enddo
> end program JBAND_TEST
>
> function FORTJBAND (tbar)
> use STUFF; implicit none
> interface
> function JBAND (tbar) bind(c)
> import JBAND, c_long_double
> import tbar, c_long_double
> end function JBAND
> end interface
> real(dbl) :: FORTJBAND
> real(qud) :: tbar
> FORTJBAND = JBAND (tbar)
> end function FORTJBAND
>
> I run this using this script
>
> g++ -o jband.o jband.cpp
That's command is wrong. Should be:
g++ -c -o jband.o jband.cpp
> gfortran -o jbandtest.o jbandtest.f90
> gfortran jband.o jbandtest.o
> ./a.out << eoi
> 1.0
> -1
> eoi
> rm a.out jband.o jbandtest.o
>
> and I get this output
>
> /usr/bin/ld:
> /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in
> function `_start':
> (.text+0x1b): undefined reference to `main'
> collect2: error: ld returned 1 exit status
> jbandtest.f90:21:31:
>
> 21 | import JBAND, c_long_double
> | 1
> Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> does not exist.
> jbandtest.f90:22:30:
>
> 22 | import tbar, c_long_double
> | 1
> Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> does not exist.
> jbandtest.f90:27:14:
>
> 27 | FORTJBAND = JBAND (tbar)
> | 1
> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(4)
> [...]
>
> So there is a communication problem with agreeing on the C++
> type long double.
> I have tried making everything in jband plain double, making
> the two statements
>
> import JBAND, c_double
> import tbar, c_double
>
> but now it says that C-double doesn't exist.
>
> Any ideas?
>
>
>
> --
> Dieter Britz
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-10 09:51 -0700 |
| Message-ID | <1cb73971-2d9b-45c7-819a-51ee45913456n@googlegroups.com> |
| In reply to | #91612 |
On Saturday, September 9, 2023 at 11:54:53 AM UTC+3, db wrote:
> I want to call a C++ function from Fortran. The function is
> called jband, in the file jband.cpp. The function is of type
> long double, and so is its argument tbar.
> I wrote this:
>
> module STUFF
> integer, parameter :: dbl=selected_real_kind(14)
> integer, parameter :: qud=selected_real_kind(30)
> end module STUFF
> program JBAND_TEST
> use STUFF; implicit none
> real(dbl) :: curr, FORTJBAND
> real(qud) :: tbar
> do
> read *, tbar
> if (tbar < 0) exit
> curr = FORTJBAND (tbar)
> print '(" curr =", f10.4)', curr
> enddo
> end program JBAND_TEST
>
> function FORTJBAND (tbar)
> use STUFF; implicit none
> interface
> function JBAND (tbar) bind(c)
> import JBAND, c_long_double
> import tbar, c_long_double
> end function JBAND
> end interface
> real(dbl) :: FORTJBAND
> real(qud) :: tbar
> FORTJBAND = JBAND (tbar)
> end function FORTJBAND
>
> I run this using this script
>
> g++ -o jband.o jband.cpp
> gfortran -o jbandtest.o jbandtest.f90
> gfortran jband.o jbandtest.o
> ./a.out << eoi
> 1.0
> -1
> eoi
> rm a.out jband.o jbandtest.o
>
> and I get this output
>
> /usr/bin/ld:
> /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in
> function `_start':
> (.text+0x1b): undefined reference to `main'
> collect2: error: ld returned 1 exit status
> jbandtest.f90:21:31:
>
> 21 | import JBAND, c_long_double
> | 1
> Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> does not exist.
> jbandtest.f90:22:30:
>
> 22 | import tbar, c_long_double
> | 1
> Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> does not exist.
> jbandtest.f90:27:14:
>
> 27 | FORTJBAND = JBAND (tbar)
> | 1
> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(4)
> [...]
>
> So there is a communication problem with agreeing on the C++
> type long double.
> I have tried making everything in jband plain double, making
> the two statements
>
> import JBAND, c_double
> import tbar, c_double
>
> but now it says that C-double doesn't exist.
>
> Any ideas?
>
>
>
> --
> Dieter Britz
I manged to pass link. 99% of the problems appear to have nothing to do
with C++ language. It's partly bad Fortran, partly wrong size of floating-point
types and partly forgotten -c flag in compilation commands.
That's my Fortran (f90) source code:
module STUFF
integer, parameter :: dbl=selected_real_kind(14)
integer, parameter :: qud=selected_real_kind(30)
end module STUFF
module abc
use, intrinsic :: iso_c_binding
interface
function JBAND (tbar) bind(c)
import c_long_double
real(c_long_double) :: JBAND
real(c_long_double) :: tbar
end function JBAND
end interface
end module abc
function FORTJBAND (tbar)
use STUFF;
use abc;
implicit none
real(dbl) :: FORTJBAND
real(qud) :: tbar
real(10) :: tbar10
real(10) :: res10
tbar10 = tbar
res10 = JBAND (tbar10)
FORTJBAND = res10
end function FORTJBAND
program JBAND_TEST
use STUFF;
implicit none
real(dbl) :: curr, FORTJBAND
real(qud) :: tbar
do
read *, tbar
if (tbar < 0) exit
curr = FORTJBAND (tbar)
print '(" curr =", f10.4)', curr
enddo
end program JBAND_TEST
That's my C++ source code (1 line)
extern "C" long double jband(long double x) { return x; }
That's my compilation commands:
g++ -c -o jband.o jband.cpp
gfortran -c -o jbandtest.o jbandtest.f90
gfortran jband.o jbandtest.o
Now I have no idea if it works like intended or not
[toc] | [prev] | [next] | [standalone]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2023-09-11 02:49 -0700 |
| Message-ID | <5b90a0f9-0da7-425b-ae83-779459f0f50en@googlegroups.com> |
| In reply to | #91658 |
On Sunday, September 10, 2023 at 7:51:56 PM UTC+3, Michael S wrote:
> On Saturday, September 9, 2023 at 11:54:53 AM UTC+3, db wrote:
> > I want to call a C++ function from Fortran. The function is
> > called jband, in the file jband.cpp. The function is of type
> > long double, and so is its argument tbar.
> > I wrote this:
> >
> > module STUFF
> > integer, parameter :: dbl=selected_real_kind(14)
> > integer, parameter :: qud=selected_real_kind(30)
> > end module STUFF
> > program JBAND_TEST
> > use STUFF; implicit none
> > real(dbl) :: curr, FORTJBAND
> > real(qud) :: tbar
> > do
> > read *, tbar
> > if (tbar < 0) exit
> > curr = FORTJBAND (tbar)
> > print '(" curr =", f10.4)', curr
> > enddo
> > end program JBAND_TEST
> >
> > function FORTJBAND (tbar)
> > use STUFF; implicit none
> > interface
> > function JBAND (tbar) bind(c)
> > import JBAND, c_long_double
> > import tbar, c_long_double
> > end function JBAND
> > end interface
> > real(dbl) :: FORTJBAND
> > real(qud) :: tbar
> > FORTJBAND = JBAND (tbar)
> > end function FORTJBAND
> >
> > I run this using this script
> >
> > g++ -o jband.o jband.cpp
> > gfortran -o jbandtest.o jbandtest.f90
> > gfortran jband.o jbandtest.o
> > ./a.out << eoi
> > 1.0
> > -1
> > eoi
> > rm a.out jband.o jbandtest.o
> >
> > and I get this output
> >
> > /usr/bin/ld:
> > /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in
> > function `_start':
> > (.text+0x1b): undefined reference to `main'
> > collect2: error: ld returned 1 exit status
> > jbandtest.f90:21:31:
> >
> > 21 | import JBAND, c_long_double
> > | 1
> > Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> > does not exist.
> > jbandtest.f90:22:30:
> >
> > 22 | import tbar, c_long_double
> > | 1
> > Error: Cannot IMPORT 'c_long_double' from host scoping unit at (1) -
> > does not exist.
> > jbandtest.f90:27:14:
> >
> > 27 | FORTJBAND = JBAND (tbar)
> > | 1
> > Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(4)
> > [...]
> >
> > So there is a communication problem with agreeing on the C++
> > type long double.
> > I have tried making everything in jband plain double, making
> > the two statements
> >
> > import JBAND, c_double
> > import tbar, c_double
> >
> > but now it says that C-double doesn't exist.
> >
> > Any ideas?
> >
> >
> >
> > --
> > Dieter Britz
> I manged to pass link. 99% of the problems appear to have nothing to do
> with C++ language. It's partly bad Fortran, partly wrong size of floating-point
> types and partly forgotten -c flag in compilation commands.
>
> That's my Fortran (f90) source code:
> module STUFF
> integer, parameter :: dbl=selected_real_kind(14)
> integer, parameter :: qud=selected_real_kind(30)
> end module STUFF
> module abc
> use, intrinsic :: iso_c_binding
> interface
> function JBAND (tbar) bind(c)
> import c_long_double
> real(c_long_double) :: JBAND
> real(c_long_double) :: tbar
> end function JBAND
> end interface
> end module abc
> function FORTJBAND (tbar)
> use STUFF;
> use abc;
> implicit none
> real(dbl) :: FORTJBAND
> real(qud) :: tbar
> real(10) :: tbar10
> real(10) :: res10
> tbar10 = tbar
> res10 = JBAND (tbar10)
> FORTJBAND = res10
> end function FORTJBAND
> program JBAND_TEST
> use STUFF;
> implicit none
> real(dbl) :: curr, FORTJBAND
> real(qud) :: tbar
> do
> read *, tbar
> if (tbar < 0) exit
> curr = FORTJBAND (tbar)
> print '(" curr =", f10.4)', curr
> enddo
> end program JBAND_TEST
> That's my C++ source code (1 line)
> extern "C" long double jband(long double x) { return x; }
>
> That's my compilation commands:
> g++ -c -o jband.o jband.cpp
> gfortran -c -o jbandtest.o jbandtest.f90
> gfortran jband.o jbandtest.o
>
> Now I have no idea if it works like intended or not
Tested it. It was incorrect, but by lucky chance worked on x86-64 Windows.
No such luck on x86-64 Linux.
Here is the correct syntax that works both on Windows and on Linux:
module abc
use, intrinsic :: iso_c_binding
interface
real(c_long_double) function JBAND (tbar) bind(c)
import c_long_double
real(c_long_double), value :: tbar
end function JBAND
end interface
end module abc
I actually understand why the previous version worked on Windows
despite being incorrect, but I don't believe that explanation is of
interest for OP.
[toc] | [prev] | [next] | [standalone]
| From | "https://psychedelicminds.shop/" <psychedelicsmind@gmail.com> |
|---|---|
| Date | 2023-09-11 05:14 -0700 |
| Subject | Buy Zen Mushroom Chocolate Bar Microdose |
| Message-ID | <94d2730d-4cae-455a-a378-1ffad78edcd7n@googlegroups.com> |
| In reply to | #91612 |
Email Address: psychedelicsmind(@)gmail.com Mushroom Chocolate (4000mg bar of 8 ultimate mushrooms) – A astonishing chocolate to help you conquer your day for energy, cognition and immunity. You can enjoy Mushroom Chocolate any time of day as part of a meal (try a few small pieces mixed into your morning granola or chia pudding), or as a treat to end the day. Each rich milk chocolate bar has our popular Mushroom Blend in it. It’s a difference you can feel and is the sweetest way to enjoy the benefits of the top 8 functional mushrooms. https://psychedelicminds.shop/product/200mg-shrooms-microdose/ https://psychedelicminds.shop/product/chill-plus-delta-8-gummies/ https://psychedelicminds.shop/product/dmt-carts-2/ https://psychedelicminds.shop/product/5-meo-dmt/ https://psychedelicminds.shop/product/nn-dmt-cartst/ https://psychedelicminds.shop/product/energy-focus-microdose/ https://psychedelicminds.shop/product/deadhead-chemist-dmt/ https://psychedelicminds.shop/product/cbd-shrooms-microdose/ https://psychedelicminds.shop/product/dmt-carts-for-sale/ https://psychedelicminds.shop/product/zen-mushroom-chocolate-bar/ https://psychedelicminds.shop/product/mushroom-chocolate-bar/ https://psychedelicminds.shop/product/chill-plus-delta-8-gummies/ https://psychedelicminds.shop/product/limitless-microdose/ https://psychedelicminds.shop/product/buy-300mg-shroom/ https://psychedelicminds.shop/product/yum-yum-gummies/ https://psychedelicminds.shop/product/buy-chocolate-chuckles/ https://psychedelicminds.shop/product/buy-shrooms-delta-8-thc-gummies/ https://psychedelicminds.shop/product/buy-delta-8-shroom-gummies-300mg/ https://psychedelicminds.shop/product/buy-genius-brain-mushrooms/ https://psychedelicminds.shop/product/4-aco-dmt/ https://psychedelicminds.shop/product/300mg-microdose/ https://psychedelicminds.shop/product/1p-lsd-2/ https://psychedelicminds.shop/product/zen-mushroom-chocolate-bar/ https://psychedelicminds.shop/product/200mg-shrooms-microdose/ https://psychedelicminds.shop/product/100mg-shrooms-microdose/ https://psychedelicminds.shop/product/psilocybe-stuntzii/ https://psychedelicminds.shop/product/psilocybe-semilanceata/
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c++
csiph-web