Calling Fortran package in C - visual-c++
I reference About using Fortran function in C with iso_c_binding to write a intermediate program so that Odrpack95 (http://www.netlib.org/odrpack/) can be called in C. But I encounter some problems and need someone help.
Fortran code
subroutine wrapper_ODR(FCN,N,M,NP,NQ,BETA,Y,X,&
DELTA,WE,WD,IFIXB,IFIXX,JOB,NDIGIT,TAUFAC,&
SSTOL,PARTOL,MAXIT,IPRINT,LUNERR,LUNRPT,&
STPB,STPD,SCLB,SCLD,WORK,IWORK,INFO,LOWER,UPPER) bind(C, name='wrapper_ODR')
!DEC$ ATTRIBUTES DLLEXPORT :: wrapper_ODR
use iso_c_binding
use ODRPACK95
implicit none
interface
subroutine FCN(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,&
IDEVAL,F,FJACB,FJACD,ISTOP) bind(C)
use, intrinsic :: iso_c_binding
implicit none
integer(c_int) :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ
real (c_double) :: BETA(1:NP),F(1:LDN,1:NQ),FJACB(1:LDN,1:LDNP,1:NQ), &
FJACD(1:LDN,1:LDM,1:NQ),XPLUSD(1:LDN,1:M)
integer(c_int) :: IFIXB(1:NP),IFIXX(1:LDIFX,1:M)
end subroutine
end interface
integer(c_int) :: N,M,NP,NQ
real(c_double) :: BETA(1:NP),Y(1:N,1:NQ),X(1:N,1:M)
!!!!!Optional
integer(c_int), optional :: IFIXB(:),IFIXX(:,:),JOB,NDIGIT,MAXIT&
,IPRINT,LUNERR,LUNRPT,IWORK(:),INFO
real(c_double), optional :: DELTA(:,:),&
WE(:,:,:),WD(:,:,:),TAUFAC,SSTOL,PARTOL,&
STPB(:),STPD(:,:),SCLB(:),SCLD(:,:),&
WORK(:),LOWER(:),UPPER(:)
call ODR(inter_func,N,M,NP,NQ,BETA,Y,X)
contains
subroutine inter_func(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,&
IDEVAL,F,FJACB,FJACD,ISTOP)
use REAL_PRECISION
integer :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ
REAL (KIND=R8) :: BETA(1:NP),F(1:LDN,1:NQ),FJACB(1:LDN,1:LDNP,1:NQ), &
FJACD(1:LDN,1:LDM,1:NQ),XPLUSD(1:LDN,1:M)
INTEGER :: IFIXB(1:NP),IFIXX(1:LDIFX,1:M)
integer(c_int) :: inter_IDEVAL,inter_ISTOP,inter_LDIFX,inter_LDM,&
inter_LDN,inter_LDNP,inter_M,inter_N,inter_NP,inter_NQ
real (c_double) :: inter_BETA(1:size(BETA)),inter_F(1:size(F,1),1:size(F,2)),&
inter_FJACB(1:size(FJACB,1),1:size(FJACB,3),1:size(FJACB,3)),&
inter_FJACD(1:size(FJACD,1),1:size(FJACD,2),1:size(FJACD,3)),inter_XPLUSD(1:size(XPLUSD,1),1:size(XPLUSD,2))
integer(c_int) :: inter_IFIXB(1:size(IFIXB)),inter_IFIXX(1:size(IFIXX,1),1:size(IFIXX,2))
inter_IDEVAL = IDEVAL
inter_ISTOP = ISTOP
inter_LDIFX = LDIFX
inter_LDM = LDM
inter_LDN = LDN
inter_LDNP = LDNP
inter_M = M
inter_N = N
inter_NP = NP
inter_NQ = NQ
!!!!REAL
inter_BETA = BETA
inter_F = F
inter_FJACB = FJACB
inter_FJACD = FJACD
inter_XPLUSD = XPLUSD
!!!!INTEGER[]
inter_IFIXB = IFIXB
inter_IFIXX = IFIXX
end subroutine inter_func
end subroutine wrapper_ODR
C code
(I translated and modified from simple_example.f90 inside ODRPACK95 )
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
extern "C" {
void wrapper_ODR(void(*FCN)(int*, int*, int*, int*, int*, int*, int*, \
double [] ,double [1][4],int [], int [],int* ,\
int*, double [1][4],double [1][2][4],double [] ,int* ),\
int *N,int *M,int *NP,int *NQ,double BETA[],double Y[1][4],double X[1][4],\
double DELTA[1][4],double WE[],double WD[],int IFIXB[],int IFIXX[],\
int *JOB,int *NDIGIT,double *TAUFAC,double *SSTOL, double *PARTOL,\
int *MAXIT, int *IPRINT, int *LUNERR, int *LUNRPT,double STPB[],\
double STPD[], double SCLB[], double SCLD[], double WORK[], double IWORK[],\
int *INFO, double LOWER[], double UPPER[]);
}
void FCN(int *N, int *M, int *NP, int *NQ, int *LDN, int *LDM, int *LDNP,\
double BETA[], double XPLUSD[1][4], int IXIFB[], int IFIXX[],int *LDIFX,\
int *IDEVAL, double F[1][4], double FJACB[1][2][4], double FJACD[],int *ISTOP){
// BETA[NP], XPLUSD[M][LDN], IXIFB[NP], IFIXX[M][LDIFX], F[NQ][LDN], FJACB[NQ][LDNP][LDN], FJACD[NQ][LDM][LDN]
*ISTOP =5;
if (fmod(*IDEVAL,10.0)!=0) {
for (int i = 0; i < *N; i++) {
F[0][i] = BETA[0] * XPLUSD[0][i] + BETA[1];
}
}
}
int main(){
//X[M][N] Y[NQ][N],BETA[NP]
int NP = 2, N = 4, M = 1, NQ = 1;
double BETA[] = { 2.0, 0.5 };
double X[1][4] = { 0.0, 1.0, 2.0, 3.0 };
double Y[1][4] = { 2.0, 5.0, 8.0, 11.0 };
wrapper_ODR(&FCN, &N, &M, &NP, &NQ, BETA, Y, X, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, NULL);
system("pause");
return 0;
}
Where NP = 2, N = 4,M = 1, NQ = 1, LDN = 4, LDM = 1, LDNP = 2,LDIFX = 4
Problems
ISTOP is used for stopping regression procedure if ISTOP is not equal to 0. However when C code above is executed, no matter what ISTOP is, it continues regression procedure. It seems that ISTOP doesn't pass to subroutine inter_func.
In Fortran code, comment parts with ! denote as passing array data parts. Well it doesn't ring any bell how to pass array data from C to Fortran or Fortran to C by inter_ variable.
Updated
I modify C and Fortran code above, the result shown below:
In C code, I set ISTOP = 5, but the result report shows it is 0.
Then if ODRPACK procedure succeeds, it should be like this:
And here is also Fortran code modified from simple_example.f90, It should be the same with C code:
PROGRAM ODRPACK95_EXAMPLE
USE ODRPACK95
USE REAL_PRECISION
REAL (KIND=R8), ALLOCATABLE :: BETA(:),X(:,:),Y(:,:)
INTEGER :: NP,N,M,NQ
INTERFACE
SUBROUTINE FCN(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,&
IDEVAL,F,FJACB,FJACD,ISTOP)
USE REAL_PRECISION
INTEGER :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ
REAL (KIND=R8) :: BETA(NP),F(LDN,NQ),FJACB(LDN,LDNP,NQ), &
FJACD(LDN,LDM,NQ),XPLUSD(LDN,M)
INTEGER :: IFIXB(NP),IFIXX(LDIFX,M)
END SUBROUTINE FCN
END INTERFACE
NP = 2
N = 4
M = 1
NQ = 1
ALLOCATE(BETA(NP),X(N,M),Y(N,NQ))
BETA(1:2) = (/ 2.0_R8, 0.5_R8 /)
X(1:4,1) = (/ 0_R8, 1_R8, 2_R8, 3_R8 /)
Y(1:4,1) = (/ 2_R8, 5_R8, 8_R8, 11_R8 /)
CALL ODR(FCN,N,M,NP,NQ,BETA,Y,X)
pause
END PROGRAM ODRPACK95_EXAMPLE
SUBROUTINE FCN(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,&
IDEVAL,F,FJACB,FJACD,ISTOP)
USE REAL_PRECISION
INTEGER :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ, I
REAL (KIND=R8) :: BETA(NP),F(LDN,NQ),FJACB(LDN,LDNP,NQ), &
FJACD(LDN,LDM,NQ),XPLUSD(LDN,M)
INTEGER :: IFIXB(NP),IFIXX(LDIFX,M)
ISTOP = 0
!Calculate model.
IF (MOD(IDEVAL,10).NE.0) THEN
DO I=1,N
F(I,1) = BETA(1)*XPLUSD(I,1)+BETA(2)
END DO
END IF
END SUBROUTINE FCN
It seems that the variable value of C function FCN doesn't pass to wrapper_ODR, but I don't know where are my problems? Could someone help me?
Related
Best data type and rounding function for weight and currency variables
I need to multiply two values - weight and currency (Visual c++, mfc). E.g.: a=11.121; b=12.11; c=a*b; Next I have to round "с" to 2 digits after point (currency value, e.g. 134.68). What the best data types and rounding function for this variables? The rounding procedure must be mathematically correct. P.S. The problem was solved by very ugly but working part of code: CString GetPriceSum(CString weight,CString price) { price.Replace(".", ""); price = price + "0"; if (weight.Find(".") == -1) { weight = weight + ".000"; } weight.Replace(".", ""); unsigned long long int iprice = atoi(price); unsigned long long int iweight = atoi(weight); unsigned long long int isum = iprice * iweight; CString sum = ""; sum.Format("%llu", isum); CString r1 = sum.Right(1); if (atoi(r1) >= 5) { isum += 10; } CString r2 = sum.Mid(sum.GetLength() - 2, 1); if (atoi(r2) >= 5) { isum += 100; sum.Format("%llu", isum);} r2 = sum.Mid(sum.GetLength() - 3, 1); if (atoi(r2) >= 5) { isum += 1000; sum.Format("%llu", isum);} r2 = sum.Mid(sum.GetLength() - 4, 1); if (atoi(r2) >= 5) { isum += 10000; sum.Format("%llu", isum);} CString finsum = ""; finsum.Format("%llu", isum); finsum.Insert(finsum.GetLength() - 6, "."); finsum.Delete(finsum.GetLength() - 4, 4); if (finsum.Left(1) == ".") { finsum = "0" + finsum; } return finsum; }
How about this: let's start from API I use, counts values using some other language. And they round they values mathematically correct. In your other question, you got those value as strings. You can construct an integer from those digits (remove decimal point). Assuming that the product fits in a 64-bit int, you can multiply them exactly. Now you can manually round to a desired precision and drop unneeded digits. Code example (you may want to add error checking): #define _CRT_SECURE_NO_WARNINGS #include <string> #include <iostream> #include <sstream> int main() { std::string a = "40.50"; std::string b = "0.490"; long long l1, dec1, l2, dec2; sscanf(a.data(), "%lld.%lld", &l1, &dec1); l1 = l1 * 100 + dec1; sscanf(b.data(), "%lld.%lld", &l2, &dec2); l2 = l2 * 1000 + dec2; long long r = l1 * l2; r /= 100; int rem = r % 10; r /= 10; if (rem >= 5) r++; std::stringstream ss; ss << r / 100 << "." << std::setw(2) << std::setfill('0') << r % 100; std::cout << ss.str(); } You can also use stringstream instead of sscanf to parse the strings.
af::array conversion to float or double
I have been experimenting with the RcppArrayFire Package, mostly rewriting some cost functions from RcppArmadillo and can't seem to get over "no viable conversion from 'af::array' to 'float'. I have also been getting some backend errors, the example below seems free of these. This cov-var example is written poorly just to use all relevant coding pieces from my actual cost function. As of now it is the only addition in a package generated by, "RcppArrayFire.package.skeleton". #include "RcppArrayFire.h" #include <Rcpp.h> // [[Rcpp::depends(RcppArrayFire)]] // [[Rcpp::export]] float example_ols(const RcppArrayFire::typed_array<f32>& X_vect, const RcppArrayFire::typed_array<f32>& Y_vect){ int Len = X_vect.dims()[0]; int Len_Y = Y_vect.dims()[0]; while( Len_Y < Len){ Len --; } float mean_X = af::sum(X_vect)/Len; float mean_Y = af::sum(Y_vect)/Len; RcppArrayFire::typed_array<f32> temp(Len); RcppArrayFire::typed_array<f32> temp_x(Len); for( int f = 0; f < Len; f++){ temp(f) = (X_vect(f) - mean_X)*(Y_vect(f) - mean_Y); temp_x(f) = af::pow(X_vect(f) -mean_X, 2); } return af::sum(temp)/af::sum(temp_x); } /*** R X <- 1:10 Y <- 2*X +rnorm(10, mean = 0, sd = 1) example_ols(X, Y) */
The first thing to consider is the af::sum function, which comes in different forms: An sf::sum(af::array) that returns an af::array in device memory and a templated af::sum<T>(af::array) that returns a T in host memory. So the minimal change to your example would be using af::sum<float>: #include "RcppArrayFire.h" #include <Rcpp.h> // [[Rcpp::depends(RcppArrayFire)]] // [[Rcpp::export]] float example_ols(const RcppArrayFire::typed_array<f32>& X_vect, const RcppArrayFire::typed_array<f32>& Y_vect){ int Len = X_vect.dims()[0]; int Len_Y = Y_vect.dims()[0]; while( Len_Y < Len){ Len --; } float mean_X = af::sum<float>(X_vect)/Len; float mean_Y = af::sum<float>(Y_vect)/Len; RcppArrayFire::typed_array<f32> temp(Len); RcppArrayFire::typed_array<f32> temp_x(Len); for( int f = 0; f < Len; f++){ temp(f) = (X_vect(f) - mean_X)*(Y_vect(f) - mean_Y); temp_x(f) = af::pow(X_vect(f) -mean_X, 2); } return af::sum<float>(temp)/af::sum<float>(temp_x); } /*** R set.seed(1) X <- 1:10 Y <- 2*X +rnorm(10, mean = 0, sd = 1) example_ols(X, Y) */ However, there are more things one can improve. In no particular order: You don't need to include Rcpp.h. There is an af::mean function for computing the mean of an af::array. In general RcppArrayFire::typed_array<T> is only needed for getting arrays from R into C++. Within C++ and for the way back you can use af::array. Even when your device does not support double, you can still use double values on the host. In order to get good performance, you should avoid for loops and use vectorized functions, just like in R. You have to impose equal dimensions for X and Y, though. Interestingly I get a different result when I use vectorized functions. Right now I am not sure why this is the case, but the following form makes more sense to me. You should verify that the result is what you want to get: #include <RcppArrayFire.h> // [[Rcpp::depends(RcppArrayFire)]] // [[Rcpp::export]] double example_ols(const RcppArrayFire::typed_array<f32>& X_vect, const RcppArrayFire::typed_array<f32>& Y_vect){ double mean_X = af::mean<double>(X_vect); double mean_Y = af::mean<double>(Y_vect); af::array temp = (X_vect - mean_X) * (Y_vect - mean_Y); af::array temp_x = af::pow(X_vect - mean_X, 2.0); return af::sum<double>(temp)/af::sum<double>(temp_x); } /*** R set.seed(1) X <- 1:10 Y <- 2*X +rnorm(10, mean = 0, sd = 1) example_ols(X, Y) */ BTW, an even shorter version would be: #include <RcppArrayFire.h> // [[Rcpp::depends(RcppArrayFire)]] // [[Rcpp::export]] af::array example_ols(const RcppArrayFire::typed_array<f32>& X_vect, const RcppArrayFire::typed_array<f32>& Y_vect){ return af::cov(X_vect, Y_vect) / af::var(X_vect); } Generally it is a good idea to use the in-build functions as much as possible.
garbage in loop for no reason
i wrote a function that receives a string as a char array and converts it to an int: int makeNumFromString(char Str[]) { int num = 0, len = 0; int p; len = strlen(Str); for (p = 0; p<len; p++) { num = num * 10 + (Str[p] - 48); } return num; } the problem is that no matter how long the string i input is, when "p" gets to 10 the value of "num" turns to garbage!!! i tried debbuging and checking the function outside of the larger code but no success. what could be the problem and how can i fix it? THANKS
Perhaps your int can only store 32 bits, so the number cannot be higher than 2,147,483,647. Try using a type for num with more storage, like long.
Difference between int and double in C++ Visual Studio
I am making a simple program which abstracts complex numbers and complex number operations. I started out with integer data types for my imaginary and real aspects of my complex numbers because of my vast ignorance when, after coding addition, subtraction and multiplication successfully, I realized that for division I would need to use doubles. When I switched to doubles I got bad results from my previous three calculations which worked wonderfully when the values were stored as ints. Can someone please explain to me what is so fundamentally different about ints and doubles in c++ that makes my code work fine for int but die when I try using doubles? I have pasted my code for reference. #include "Complex.h" #include <math.h> #include <stdio.h> #include <stdlib.h> Complex::Complex(){ real = 0; imaginary = 0; } Complex::Complex(double givenReal, double givenImaginary) { real = givenReal; imaginary = givenImaginary; } double Complex::getImaginary(){ return imaginary; } double Complex::getReal(){ return real; } double Complex::getMagnitude(){ //magnitude = sqrt(pow(real,2)+pow(magnitude,2)); return magnitude; } Complex Complex::operator+(Complex n){ Complex j = Complex(); j.real = real + n.real; j.imaginary = imaginary + n.imaginary; return j; } Complex Complex::operator-(Complex n){ Complex j = Complex(); j.real = real - n.real; j.imaginary = imaginary - n.imaginary; return j; } Complex Complex::operator*(Complex n){ Complex j = Complex(); j.real = (real * n.real)-(imaginary * n.imaginary); j.imaginary = (real * n.imaginary) + (imaginary * n.real); return j; } Complex Complex::operator/(Complex n){ Complex j = Complex(); j.real = ((real * n.real) + (imaginary * n.imaginary))/(n.real*n.real + n.imaginary*n.imaginary); j.imaginary = ((imaginary*n.real)-(real * n.imaginary))/(n.real*n.real + n.imaginary*n.imaginary); return j; } int main(){ Complex a = Complex(1, 3); Complex b = Complex(4, 8); Complex c = a+b; printf("Adding a and b\nExpected: (5,11)\nActual: (%d,%d)\n",c.getReal(), c.getImaginary()); c = a-b; printf("Subtracting b from a\nExpected: (-3,-5)\nActual: (%d,%d)\n",c.getReal(), c.getImaginary()); c = a*b; printf("Multiplying a and b\nExpected: (-20,20)\nActual: (%d,%d)\n",c.getReal(), c.getImaginary()); c = a/b; printf("Dividing a by b\nExpected: (.35,.05)\nActual: (%d,%d)\n",c.getReal(), c.getImaginary()); system ("pause"); } Output: Adding a and b Expected: (5,11) Actual: (0,1075052544) Subtracting b from a Expected: (-3,-5) Actual: (0,-1073217536) Multiplying a and b Expected: (-20,20) Actual: (0,-1070333952) Dividing a by b Expected: (.35,.05) Actual: (1610612736,1071015526)
What every C/C++ programmer should know about printf format specifiers are: %d is for int, %f is for double.
encryption in c++
edit: I am implementing an algorithm in c++. #include<iostream> #include<math.h> #include<string> using namespace std; int gcd(int n,int m) { if(m<=n && n%m ==0) return m; if(n<m) return gcd(m,n); else return gcd(m,n%m); } int REncryptText(char m) { int p = 11, q = 3; int e = 3; int n = p * q; int phi = (p - 1) * (q - 1); int check1 = gcd(e, p - 1); int check2 = gcd(e, q - 1); int check3 = gcd(e, phi); // // Compute d such that ed ≡ 1 (mod phi) //i.e. compute d = e-1 mod phi = 3-1 mod 20 //i.e. find a value for d such that phi divides (ed-1) //i.e. find d such that 20 divides 3d-1. //Simple testing (d = 1, 2, ...) gives d = 7 // double d = Math.Pow(e, -1) % phi; int d = 7; // public key = (n,e) // (33,3) //private key = (n,d) //(33 ,7) double g = pow(m,e); int ciphertext = g %n; // Now say we want to encrypt the message m = 7, c = me mod n = 73 mod 33 = 343 mod 33 = 13. Hence the ciphertext c = 13. //double decrypt = Math.Pow(ciphertext, d) % n; return ciphertext; } int main() { char plaintext[80],str[80]; cout<<" enter the text you want to encrpt"; cin.get(plaintext,79); int l =strlen(plaintext); for ( int i =0 ; i<l ; i++) { char s = plaintext[i]; str[i]=REncryptText(s); } for ( int i =0 ; i<l ; i++) { cout<<"the encryption of string"<<endl; cout<<str[i]; } return 0; } error message error C2296: '%' : illegal, left operand has type 'double'
Try this. Simple 2 way encryption for C#