C++ -> Rcpp 写経その3『配列で大量のデータ処理』

// sample06.cpp
#include <stdio.h>

main(void)
{
  int score1, score2;
  double mean;
    
  printf("Input the score of No.1 = ");
  scanf("%d", &score1 );
  printf("Input the score of No.2 = ");
  scanf("%d", &score2 );
    
  mean = (double)( score1 + score2 )/2.0;
    
  printf("The mean score is %lf \n", mean );
}
// sample06R.cpp
#include <stdio.h>
#include <Rcpp.h>
using namespace Rcpp;

// 与えた x に対する y = sqrt(x) を計算する。
// [[Rcpp::export]]
double sample06(int score1, int score2)
{
  //int score1, score2;
  double mean;
    
  //printf("Input the score of No.1 = ");
  //scanf("%d", &score1 );
  //printf("Input the score of No.2 = ");
  //scanf("%d", &score2 );
    
  mean = (double)( score1 + score2 )/2.0;
    
  //printf("The mean score is %lf \n", mean );
  return mean;
}
/*** R
score1 = 67; score2 =86
sample06(score1,score2)
*/
  • その6−2、先頭10人分の平均
#include <stdio.h>
#define N 10

main(void)
{
  int score[N];                        // 配列の宣言
  int n, sum;
  double mean;
    
  for( n=0 ; n<N ; n++ ){           // 配列の各要素に値を入力
    printf("Input the score of No.%d = ", n );
    scanf("%d", &score[n] );
  }

  sum = 0;
  for( n=0 ; n<N ; n++ ){           // 合計点の計算
    sum += score[n];
  }
  mean = (double)sum/N;                // 平均点の計算

  printf("The mean score is %lf\n", mean );
}
// sample06_2R.cpp
#include <stdio.h>
#include <Rcpp.h>
using namespace Rcpp;

#define N 10

// [[Rcpp::export]]
double sample06_2(NumericVector score)
{
  //int score[N];                        // 配列の宣言
  int n, sum;
  double mean;
    
  for( n=0 ; n<N ; n++ ){           // 配列の各要素に値を入力
    printf("Input the score of No.%d = ", n );
    scanf("%d", &score[n] );
  }

  sum = 0;
  for( n=0 ; n<N ; n++ ){           // 合計点の計算
    sum += score[n];
  }
  mean = (double)sum/N;                // 平均点の計算

  //printf("The mean score is %lf\n", mean );
  return mean;
}
/*** R
x <- sample(0:100,20)
sample06_2(x)
mean(x)
mean(x[1:10])
*/

[C++][Rcpp][RcppArmadillo]C++ -> Rcpp 写経その4『関数で計算の分担』

// sample09.cc
#include <stdio.h>

void CalcSeries( void )  // 関数CalcSeries() の定義の開始
{
  double r, term=1.0, sum=0.0;
  
  printf("Input a number below 1.0 =");
  scanf("%lf", &r );     // 比例乗数 r の入力受け付け

  while( term > 0.000001 ){   // 足し上げる項が0より大きい間繰り返す
    sum  += term;        // 項の足し上げ
    term *= r;           // 乗数をかけて次の項の値とする
  }

  printf("The total of this series is %lf\n", sum );
}                        // 関数の定義の終了
    
main( void )
{
  CalcSeries();          // 関数CalcSeries() の実行 その1
  CalcSeries();          // 関数CalcSeries() の実行 その2
}
// sample09R.cpp
#include <stdio.h>
#include <Rcpp.h>
using namespace Rcpp;

double CalcSeries(double r, double eps)  // 関数CalcSeries() の定義の開始
{
  //double r, term=1.0, sum=0.0;
  double term=1.0;
  double sum=0.0;
  
  //printf("Input a number below 1.0 =");
  //scanf("%lf", &r );     // 比例乗数 r の入力受け付け

  while( term > eps ){   // 足し上げる項が0より大きい間繰り返す
    sum  += term;        // 項の足し上げ
    term *= r;           // 乗数をかけて次の項の値とする
  }

  //printf("The total of this series is %lf\n", sum );
  return sum;
}                        // 関数の定義の終了

// [[Rcpp::export]]
    
double sample09( double r,double eps=0.000001 )
{
  return CalcSeries(r,eps);          // 関数CalcSeries() の実行 その1
  //CalcSeries();          // 関数CalcSeries() の実行 その2
}
/*** R
x <- 0.7
eps <- 0.000001
sample09(x,eps)
*/
  • その10 関数のプロトタイプ宣言。main()の後にmain()で使う関数を書きたいときは、せめてそういう関数があることを宣言(プロトタイプ宣言)しておくことが必要
// sample10.cpp
#include <stdio.h>

double CalcSeries( double );  // 関数CalcSeries() のprototype宣言
    
int main( void )
{
  double r, sum;

  printf("Input a number below 1.0 =");
  scanf("%lf", &r );            // 比例乗数 r の入力受け付け その1
  sum = CalcSeries(r);          // 関数CalcSeries() の実行 その1
  printf("The total of this series is %lf\n", sum );

  printf("Input a number below 1.0 =");
  scanf("%lf", &r );            // 比例乗数 r の入力受け付け その2
  sum = CalcSeries(r);          // 関数CalcSeries() の実行 その2
  printf("The total of this series is %lf\n", sum );

  return(0);
}



double CalcSeries( double r )  // 関数CalcSeries() の定義の開始
{
  double term=1.0, sum=0.0; // 局所変数の宣言と定義
  
  while( term > 0.000001 ){   // 足し上げる項が0より大きい間繰り返す
    sum  += term;        // 項の足し上げ
    term *= r;           // 乗数をかけて次の項の値とする
  }

  return( sum );         // 合計の値を呼び出し元へ戻す
}                        // 関数の定義の終了
// sample10R.cpp
#include <stdio.h>
#include <Rcpp.h>
using namespace Rcpp;

double CalcSeries( double, double);  // 関数CalcSeries() のprototype宣言

// [[Rcpp::export]]
double sample10( double r,double eps=0.000001 )
{
  return CalcSeries(r,eps);          // 関数CalcSeries() の実行 その1
  //CalcSeries();          // 関数CalcSeries() の実行 その2
}

double CalcSeries(double r, double eps)  // 関数CalcSeries() の定義の開始
{
  //double r, term=1.0, sum=0.0;
  double term=1.0;
  double sum=0.0;
  
  //printf("Input a number below 1.0 =");
  //scanf("%lf", &r );     // 比例乗数 r の入力受け付け

  while( term > eps ){   // 足し上げる項が0より大きい間繰り返す
    sum  += term;        // 項の足し上げ
    term *= r;           // 乗数をかけて次の項の値とする
  }

  //printf("The total of this series is %lf\n", sum );
  return sum;
}                        // 関数の定義の終了

    
/*** R
x <- 0.7
eps <- 0.000001
sample10(x,eps)
*/
  • その13 ベクトルごと渡す。Cppでは一仕事だけれど、Rcppがうまくやってくれる
// sample13.cc
#include <stdio.h>

void Copy1DArray( int [] , int [] );
void Print1DArray( int [] );

int main(void)
{
     // 配列の宣言、一方は初期化する。
  int a[10], b[10]={0,1,2,3,4,5,6,7,8,9};

  Copy1DArray( a, b );     // 配列ごとのコピー
  Print1DArray( a );       // 配列ごとの表示

  return(0);
}

// 配列をコピーする関数
void Copy1DArray( int x[] , int y[] )
{
  int n;
  for( n=0 ; n<10 ; n++ ){
    x[n] = y[n];
  }
}

// 配列の要素を表示する関数
void Print1DArray( int x[] )
{
  int n;
  for( n=0 ; n<10 ; n++ ){
    printf("%d ", x[n] );
  }
}
// sample13R.cpp
#include <stdio.h>
#include <Rcpp.h>
using namespace Rcpp;


NumericVector Copy1DArray( NumericVector );
//void Print1DArray( int [] );

// [[Rcpp::export]]
NumericVector sample13(NumericVector x)
{
     // 配列の宣言、一方は初期化する。
  //int a[10], b[10]={0,1,2,3,4,5,6,7,8,9};

  NumericVector b = Copy1DArray( x );     // 配列ごとのコピー
  //Print1DArray( a );       // 配列ごとの表示

  return(b);
}

// 配列をコピーする関数
NumericVector Copy1DArray( NumericVector x  )
{
  int k = x.size();
  NumericVector y(k);
  for(int n=0 ; n<k ; n++ ){
    y[n] = x[n];
  }
  return y;
}

/*** R
x <- runif(10)
sample13(x)
*/

// 配列の要素を表示する関数
//void Print1DArray( int x[] )
//{
//  int n;
//  for( n=0 ; n<10 ; n++ ){
//    printf("%d ", x[n] );
//  }
//}
  • これ以降はUNIXでできるグラフィクス、とかになるので、この先はRcpp、RcppArmadilloとの連携に進むことにする