Boost Library 1.75.0 을 설치하고

Visual Studio 2019 의 명령행 컴파일러 cl 로 컴파일하였다.

컴파일하기 전에 미리 환경변수 BOOST_LIB_PATH 와 MPIR_LIB_PATH 를 각각

Boost Library 와 MPIR Library 가 있는 경로로 설정해 놓아야 한다.

 

/*
 * Filename: CalculateAreaOfDiskWithBoosLibrary.cpp
 *
 *       Purpose: Test floating point numbers of arbitrary precision.
 *
 * Compile: cl CalculateAreaOfDiskWithBoosLibrary.cpp /I%BOOST_LIB_PATH% /I%MPIR_LIB_PATH% /EHsc /utf-8 MPIR_LIB_PATHmpir.lib
 * Execute: CalculateAreaOfDiskWithBoosLibrary
 *
 * Date: 2021.03.29
 * Revised Author: pkim ((AT)) scripts ((DOT)) pe ((DOT)) kr 
 *
 * See: www.boost.org/doc/libs/1_56_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/gmp_float.html
 */
 
#include<iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/math/constants/constants.hpp>

using boost::multiprecision::cpp_dec_float_50;
using boost::multiprecision::cpp_dec_float_100;
using boost::multiprecision::cpp_dec_float;
using boost::multiprecision::cpp_bin_float_quad;

#include <boost/multiprecision/gmp.hpp>
using namespace boost::multiprecision;

typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<40> > flp_type_dec_40;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<49> > flp_type_dec_49;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<99> > flp_type_dec_99;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<101> > flp_type_dec_101;


using namespace std;

template<typename T>
inline T area_of_a_circle(T r)
{
    // pi represent predefined constant having value
    // 3.1415926535897932384...
    using boost::math::constants::pi;
    return pi<T>() * r * r;
}



void testFloatNumbers()
{
	float radius_f = 123.0/ 100;
	float area_f = area_of_a_circle(radius_f);

	double radius_d = 123.0 / 100;
	double area_d = area_of_a_circle(radius_d);

	cpp_dec_float_50 r_mp = 123.0 / 100;
	cpp_dec_float_50 area_mp = area_of_a_circle(r_mp);

	cpp_dec_float_100  r_100 = 123.0 / 100;
	cpp_dec_float_100 area_100 = area_of_a_circle(r_100);


	cpp_bin_float_quad  r_quad= 123.0 / 100;
	cpp_bin_float_quad area_quad = area_of_a_circle(r_quad);


	flp_type_dec_40  r_40 = 123.0 / 100;
	flp_type_dec_40 area_40 = area_of_a_circle(r_40);


	flp_type_dec_49  r_49 = 123.0 / 100;
	flp_type_dec_49 area_49 = area_of_a_circle(r_49);


	flp_type_dec_99  r_99 = 123.0 / 100;
	flp_type_dec_99 area_99 = area_of_a_circle(r_99);


	flp_type_dec_101  r_101 = 123.0 / 100;
	flp_type_dec_101 area_101 = area_of_a_circle(r_101);


      using boost::math::constants::pi;
      cout << "Let be given a circle with radius, r = " << radius_d << endl;
      cout << "Calculate the area of the given circle,\n        Area = PI*r^2 = " << pi<double>() << "*" << radius_d << "^2 = " << pi<double>() << "*" << (radius_d * radius_d) << ",\nin various precisions." << endl << endl;;

	// numeric_limits::digits10 represent the number
	// of decimal digits that can be held of particular
	// data type without any loss.
	
	// Area by using float data type
	cout << " Float: "
		<< setprecision(numeric_limits<float>::digits10)
		<< area_f << endl;

	// Area by using double data type
	cout << "Double: "
		<<setprecision(numeric_limits<double>::digits10)
		<< area_d << endl;


	// Area by using Boost 40 precision Multiprecision
	cout << "Boost Multiprecision  (40 digits): "
		<< setprecision(numeric_limits<flp_type_dec_40>::digits10)
		<< area_49 << endl;

	// Area by using Boost 49 precision Multiprecision
	cout << "Boost Multiprecision  (49 digits): "
		<< setprecision(numeric_limits<flp_type_dec_49>::digits10)
		<< area_49 << endl;

	// Area by using Boost 50 precision Multiprecision
	cout << "Boost Multiprecision  (50 digits): "
		<< setprecision(numeric_limits<cpp_dec_float_50>::digits10)
		<< area_mp << endl;

	// Area by using Boost 99 precision Multiprecision
	cout << "Boost Multiprecision  (99 digits): "
		<< setprecision(numeric_limits<flp_type_dec_99>::digits10)
		<< area_99 << endl;

	// Area by using Boost 100 precidion Multiprecision
	cout << "Boost Multiprecision (100 digits): "
		<< setprecision(numeric_limits<cpp_dec_float_100>::digits10)
		<< area_100 << endl;

	// Area by using Boost 101 precision Multiprecision
	cout << "Boost Multiprecision (101 digits): "
		<< setprecision(numeric_limits<flp_type_dec_101>::digits10)
		<< area_100 << endl;

	// Area by using Boost Quaduple Multiprecision
	cout << "Boost Multiprecision  (Quadruple): "
		<< setprecision(numeric_limits<cpp_bin_float_quad>::digits10)
		<< area_quad << endl;
}


int main()
{ 
	testFloatNumbers();
	return 0;
}


/*
Output:
-------------------------------------------
Let be given a circle with radius, r = 1.23
Calculate the area of the given circle,
        Area = PI*r^2 = 3.14159*1.23^2 = 3.14159*1.5129,
in various precisions.

 Float: 4.75292
Double: 4.752915525616
Boost Multiprecision  (40 digits): 4.752915525615998053187629092943809341311
Boost Multiprecision  (49 digits): 4.752915525615998053187629092943809341310825398145
Boost Multiprecision  (50 digits): 4.7529155256159980531876290929438093413108253981451
Boost Multiprecision  (99 digits): 4.75291552561599805318762909294380934131082539814514244132288567973008216166037385350291572422559648
Boost Multiprecision (100 digits): 4.752915525615998053187629092943809341310825398145142441322885679730082161660373853502915724225596483
Boost Multiprecision (101 digits): 4.7529155256159980531876290929438093413108253981451424413228856797300821616603738535029157242255964827
Boost Multiprecision  (Quadruple): 4.75291552561599805318762909294381
-------------------------------------------
*/

 

 

 

Posted by Scripter
,

 

C 언어로 동적 메모리(dynamic memory)를 할당빋으려면 malloc() 함수나 calloc() 함수를 사용하고, 해제할 때는 free() 함수를 사용한다.

C++ 언에서도 이를 사용해도 되지만 메모리 할당과 관리를 객체의 생성과 소멸 과정 중에 혹은 함수의 호출과 리턴의 과정 중에 프로그래머가 일일이 간섭하려면 귀찮기도 하고, 잠간의 실수로, 심각한 버그가 발생하여 치명적인 결함이 생길 수도 있다.

C++ 언어에서는 배열의 메모리 할당과 해제를 C 언어 보다 좀  더 안전하고 편하게 해 주는

new 타입[] 과  delete[] 포인터변수 형태의  구문이 있다.

예를 들어, 부동소수점수 double 타입의 값을 10개 저장하는 공간을 할당받고 해제하는 구문의 예는 다음과 같다.

 

    double *my_arr = new double[10] { 1, 2, 3 };

    ...........적당히 사용...................

    delete[] my_arr;

 

혹은

 

    double *my_arr = new double[10];

    my_arr[0] = 1;

    my_arr[1] = 2;

    my_arr[2] = 3;

    ...........적당히 사용...................

    delete[] my_arr;

 

그런데 가끔씩 배열의 크기를 변경헤야 하는 경우가 있는데,

이럴 때는 다음 예를 상황에 맞게 수정하여 쓰면 된다.

matrix 형태의 배열을 취급하는 예도 포함되어 있는 소스이다.

 

// Filename: TestResizeOfArray01.cpp
//
// Compile: g++  -o TestResizeOfArray01 TestResizeOfArray01.cpp
// Execute: ./TestResizeOfArray01
//     Or
// Compile: cl TestResizeOfArray01.cpp /EHsc /utf-8
// Execute: TestResizeOfArray01
// Output:
//     Original size. m = 5
//     (sizeof(data) / sizeof(int)) = 2
//     [ 1  2  3  0  0 ]
//
//     Changed size. m = 10
//     (sizeof(data) / sizeof(*data)) = 2
//     [ 1  2  3  0  0  0  0  0  0  0 ]
//
//
//     Original size. m = 3, n = 4
//     (sizeof(data) / sizeof(int)) = 2
//     [[    1    2    3    1  ]
 //     [    2    3    4    2  ]
 //     [    1    0    0    0  ]]
//
//     Changed size. m = 6, n = 8
//     (sizeof(data) / sizeof(*data)) = 2
//     [[    1    2    3    1    0    0    0    0  ]
//      [    2    3    4    2    0    0    0    0  ]
//      [    1    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]]
//
// Data: 2021.02.23 ~ 2021.02.24
//
// Copyright 2021 (C) pkim (_AT_) scripts (_DOT_) pe (_DOT_) kr

#include <stdlib.h>
	
#include <iostream>
#include <iterator>   // for std::size
#include <algorithm> // for copy
#include <array>
#include <iomanip>

void resize(int*& a, size_t& n)
{
   size_t new_n = 2 * n;
   int* new_a = new int[new_n];

   for (size_t i = 0; i < new_n; i++)
   {
       new_a[i] = (int) 0;
   }

   std::copy(a, a + n, new_a);
   delete[] a;
   a = new_a;
   n = new_n;
}

void print1DArray(int *data, size_t n)
{
    std::cout << "[";
    for (size_t i = 0; i < n; i++)
    {
        std::cout << " " << data[i] << " " ;
    }
    std::cout << "]" <<std::endl;
}

void test1DArray()
{
    size_t m = 5;
    int *data = new int[5] { 1, 2, 3 };

    std::cout << "Original size. m = " << m << std::endl;
    std::cout << "(sizeof(data) / sizeof(int)) = " << (sizeof(data) / sizeof(int)) << std::endl;
    print1DArray(data, m);
    std::cout << std::endl;

    resize((int *&)data, m);

    std::cout << "Changed size. m = " << m << std::endl;
    std::cout << "(sizeof(data) / sizeof(*data)) = " << (sizeof(data) / sizeof(*data)) << std::endl;
    print1DArray(data, m);
    std::cout << std::endl;
    std::cout << std::endl;
}

 resize2D(int*& a, size_t& m, size_t& n)
{
   size_t new_m= 2 * m, new_n = 2 * n, i = 0;
   int* new_a = new int[new_m * new_n];

   for (i = 0; i < new_n*new_m; i++)
   {
       new_a[i] = (int) 0;
   }

   for (i = 0; i < m; i++)
   {
       std::copy(a + i*n, a + i*n + n, new_a + i*new_n);    // copy(a[i], a[i] + 100, new_a[i]);
   }

   delete[] a;
   a = new_a;
   m = new_m;
   n = new_n;
}

void print2DArray(int *data, size_t m, size_t n)
{
    std::cout << "[[ " ;
    if ( m == 0)
    {
      	   std::cout << "]]" << std::endl;
      	   return;
    }

	if (m > 0)
	{
           for (size_t j = 0; j < n; j++)
           {
               std::cout<< " " << std::setw(3) << data[j] << " " ;
           }
           if (m > 1)
           {
               std::cout << " ]"  << std::endl;
           }
           else
           {
               std::cout << " ]]"  << std::endl;
           }

           if (m > 1)
           {
                for (size_t i = 1; i < m; i++)
                {
                	std::cout << " [ " ;
                    for (size_t j = 0; j < n; j++)
                    {
                        std::cout << " "<< std::setw(3) << data[i*n + j] << " " ;
                    }

     	              if (i < m - 1)
    	              {
                         std::cout << " ]"  << std::endl;
                    }
    	              else
    	              {
                         std::cout << " ]]"  << std::endl;
                     }
                }
           }
    }
}

void test2DArray()
{
    size_t m = 3;
    size_t n = 4;
    int *data = new int[m*n]  {  1, 2, 3 , 1, 2, 3, 4 , 2, 1 };    // { { 1, 2, 3 }, { 1, 2, 3, 4 }, {2, 1} };

    std::cout << "Original size. m = " << m << ", n = " << n << std::endl;
    std::cout << "(sizeof(data) / sizeof(int)) = " << (sizeof(data) / sizeof(int)) << std::endl;
    print2DArray((int *)&data[0], m, n);
    std::cout << std::endl;

    resize2D((int *&)data, m, n);

    std::cout << "Changed size. m = " << m << ", n = " << n << std::endl;
    std::cout << "(sizeof(data) / sizeof(*data)) = " << (sizeof(data) / sizeof(*data)) << std::endl;
    print2DArray((int *)&data[0], m, n);
    std::cout << std::endl;
}

int main()
{
    test1DArray();
    test2DArray();
    return 0;
}
Posted by Scripter
,

Visual Studio 2019 와 MSYS2 MinGW64 에서 테스트 된 소스입니다.

 혹시 MinGW 에서 컴파일되지 않으면

$ packman -S mpfr

명령으로 mpfr 라이브러리를 설치하고 컴파일하면 된다.

 

// Filename: calcGammaFn.c
//
// Compile: gcc -o calcGammaFn calcGammaFn.c -lmpfr -lgmp
// Execute: ./calcGammaFn
//     Or
// Compile: cl calcGammaFn.c /I. mpfr.lib
// Execute: calcGammaFn
//
// Date: 2021.01.28


#include <stdio.h>
#include <math.h>    // for log(10)
#include <mpfr.h>

int main()
{
  mpfr_t x; 
  int i, inex;

  mpfr_set_emin (-41);
  mpfr_init2 (x, 42);

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);      
      mpfr_subnormalize (x, inex, MPFR_RNDZ);
      mpfr_dump (x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);
      mpfr_printf("Gamma(%2d) = %2d! = %Rf\n", i, i - 1, x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);
      mpfr_printf("LogGamma(%2d) = Log(%2d!) = %Rf\n", i, i - 1, x);
  }

  printf("\n");

 double t10 = log(10.0);
 printf("log(10) = %f\n", t10);
 
  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);      
      inex = mpfr_div_d(x, x, t10,  MPFR_RNDZ);
      mpfr_printf("Log10Gamma(%2d) = Log10(%2d!) = %Rf\n", i, i - 1, x);
  }

  mpfr_clear (x);
  
  return 0;
}

/*
Output:
LogGamma( 1) = Log( 0!) = 0
LogGamma( 2) = Log( 1!) = 0
LogGamma( 3) = Log( 2!) = 0.693147
LogGamma( 4) = Log( 3!) = 1.791759
LogGamma( 5) = Log( 4!) = 3.178054
LogGamma( 6) = Log( 5!) = 4.787492
LogGamma( 7) = Log( 6!) = 6.579251
LogGamma( 8) = Log( 7!) = 8.525161
LogGamma( 9) = Log( 8!) = 10.604603
LogGamma(10) = Log( 9!) = 12.801827
LogGamma(11) = Log(10!) = 15.104413
LogGamma(12) = Log(11!) = 17.502308
LogGamma(13) = Log(12!) = 19.987214
LogGamma(14) = Log(13!) = 22.552164
LogGamma(15) = Log(14!) = 25.191221
LogGamma(16) = Log(15!) = 27.899271
LogGamma(17) = Log(16!) = 30.671860

log(10) = 2.302585

Log10Gamma( 1) = Log10( 0!) = 0
Log10Gamma( 2) = Log10( 1!) = 0
Log10Gamma( 3) = Log10( 2!) = 0.301030
Log10Gamma( 4) = Log10( 3!) = 0.778151
Log10Gamma( 5) = Log10( 4!) = 1.380211
Log10Gamma( 6) = Log10( 5!) = 2.079181
Log10Gamma( 7) = Log10( 6!) = 2.857332
Log10Gamma( 8) = Log10( 7!) = 3.702431
Log10Gamma( 9) = Log10( 8!) = 4.605521
Log10Gamma(10) = Log10( 9!) = 5.559763
Log10Gamma(11) = Log10(10!) = 6.559763
Log10Gamma(12) = Log10(11!) = 7.601156
Log10Gamma(13) = Log10(12!) = 8.680337
Log10Gamma(14) = Log10(13!) = 9.794280
Log10Gamma(15) = Log10(14!) = 10.940408
Log10Gamma(16) = Log10(15!) = 12.116500
Log10Gamma(17) = Log10(16!) = 13.320620
*/

 

 

 

 

 

Posted by Scripter
,