Programowanie w systemie UNIX/MPC
Gnu Mpc[1] jest to biblioteka C służąca do operacji arytmetycznych na liczbach zespolonych z dowolną precyzją (ang. arbitrarily high precision) i właściwym zaokrąglaniem wyniku.
Zależności / wymagania
edytujInstalacja
edytujMPC jest wbudowany w GCC od wersji 4.5, więc jeśli masz zainstalowany kompilator GCC>4.5 to bibliotekę MPC masz już zainstalowaną.
Budowanie
edytuj./configure make make check sudo make install make ps
lub:
./configure --prefix=/usr/local/mpc-0.9 --with-gmp=/usr/local/gmp-5.0.2 --with-mpfr=/usr/local/mpfr-3.0.1 make make install
Wynik:
Libraries have been installed in: /usr/local/lib If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the '-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the 'LD_RUN_PATH' environment variable during linking - use the '-Wl,-rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to '/etc/ld.so.conf'
git
edytujZ użyciem anonimowego dostępu do git:[2]
git clone https://gforge.inria.fr/git/mpc/mpc.git
pakiety
edytujMPC jest również dostępne za pośrednictwem następujących pakietów stron trzecich:[3]
- GNU Linux
- Pakiety Debiana od Squeeze: libmpc2 dla biblioteki, libmpc-dev dla plików nagłówkowych i pakiet źródłowy mpclib
- Pakiety Ubuntu od 09.04 (Jaunty): libmpc2 dla biblioteki i libmpc-dev dla plików nagłówkowych
- Pakiety Opensuse od wersji 11.2: libmpc2 dla biblioteki i mpc-devel dla plików nagłówkowych
- Pakiety Fedory w wersji rozwojowej i jako aktualizacje od wydania 11: libmpc dla biblioteki i libmpc-devel dla plików nagłówkowych
- Pakiet Arch Linux od 2009 roku: libmpc
- Pakiet NixOS od 0.14: mpc
- Pakiet Guix od wydania alfa: mpc inside multiprecision
- Pakiet zestawu kompilacji dystrybucji T2 SDE
- Port FreeBSD, więcej informacji o Freshports
- Pakiet Fink
- Pakiet Cygwin mpclib
Programy:
- Synaptic : Za pomocą Menadżera Pakietów Synaptic: libmpc (pakiet biblioteki i dev)
- aptitude : sudo aptitude install libmpc-dev libmpc2
- apt-get: sudo apt-get install libmpc-dev
Testy
edytujmake check
wynik:
Wejście do katalogu `/home/a/Pobrane/mpc-1.0.2/tests' PASS: tabs PASS: tacos PASS: tacosh PASS: tadd PASS: tadd_fr PASS: tadd_si PASS: tadd_ui PASS: targ PASS: tasin PASS: tasinh PASS: tatan PASS: tatanh PASS: tconj PASS: tcos PASS: tcosh PASS: tdiv PASS: tdiv_2si PASS: tdiv_2ui PASS: tdiv_fr PASS: tdiv_ui PASS: texp PASS: tfma PASS: tfr_div PASS: tfr_sub PASS: timag PASS: tio_str PASS: tlog PASS: tlog10 PASS: tmul PASS: tmul_2si PASS: tmul_2ui PASS: tmul_fr PASS: tmul_i PASS: tmul_si PASS: tmul_ui PASS: tneg PASS: tnorm PASS: tpow PASS: tpow_ld PASS: tpow_d PASS: tpow_fr PASS: tpow_si PASS: tpow_ui PASS: tpow_z PASS: tprec PASS: tproj PASS: treal PASS: treimref PASS: tset PASS: tsin PASS: tsin_cos PASS: tsinh PASS: tsqr PASS: tsqrt PASS: tstrtoc PASS: tsub PASS: tsub_fr PASS: tsub_ui PASS: tswap PASS: ttan PASS: ttanh PASS: tui_div PASS: tui_ui_sub GMP: include 6.0.0, lib 6.0.0 MPFR: include 3.1.1-p2, lib 3.1.1-p2 MPC: include 1.0.2, lib 1.0.2 C compiler: gcc -std=gnu99 GCC: yes GCC version: 4.8 PASS: tget_version =================== All 64 tests passed ===================
Precyzja
edytujmpfr_prec_t
Zaokrąglenie
edytujSposoby zaokrąglanie (ang. rounding Modes) liczb zespolonych typu mpc_t mają formę:[4]
MPC_RNDxy
Litery x i y oznaczają sposób dla części rzeczywistej (litera x) i urojonej (litera y) Są następujące metody:
- N oznacza do najbliższej liczby (to nearest)
- Z w kierunku zera (towards zero)
- U w (towards plus infinity)
- D (towards minus infinity)
zmienna określająca jet typu:
mpc_rnd_t
Format liczb
edytuj- liczba zmiennoprzecinkowa (brakująca część urojona jest ustawiona na +0)
- para liczb zmiennoprzecinkowych:
- oddzielonych spacją
- otoczona nawiasami
Przedrostki określające podstawę formatu liczb:
- '0b' dla liczb dwójkowych (ang. binary numbers)
- '0x' dla liczb heksadecymalnych (ang. hexadecimal numbers)
- bez przedrostka dla liczb dziesiętnych
"If base = 0, then a prefix may be used to indicate the base in which the floating-point number is written. ... The real and imaginary part may then be written in different bases. For instance, "(1.024e+3 +2.05e+3)" and "(0b1p+10 +0x802)" are valid strings for base=0 and represent the same value."
Przykłady poprawnych liczb dziesiętnych (ang. base = 10):
3.1415926 (1.25e+7 +.17) (@nan@ 2) (-0 -7) -@inf@
binarnych:
0b101 (0b101 0b1.01)
Typy
edytujmpc_t
edytujDefinicja
typedef struct { mpfr_t re; mpfr_t im; } __mpc_struct; typedef __mpc_struct mpc_t[1];
Każda część (rzeczywista i urojona) ma swoją precyzję [5]
Dostęp do części:
mpc_realref (z) mpc_imagref (z)
Funkcja
edytujmpc_conj: x - iy mpc_norm: x^2 + y^2 mpc_abs: sqrt(x^2 + y^2)
Zwracana wartość: inex
edytujinex = inexact value
"Most MPC functions have a return value of type int, which is used to indicate the position of the rounded real and imaginary parts with respect to the exact (infinite precision) values. If this integer is k, the macros MPC_INEX_RE(k) and MPC_INEX_IM(k) give 0 if the corresponding rounded value is exact, a negative value if the rounded value is less than the exact one, and a positive value if it is greater than the exact one. Similarly, functions computing a result of type mpfr_t return an integer that is 0, positive or negative depending on whether the rounded value is the same, larger or smaller then the exact result"
Jak używać w c ?
edytujEtapy użycia:[6]
- deklaracja zmiennej
- inicjalizacja
- przypisanie (ang. Assignment)
- obliczenia (ang. computing)
- zwolnienie pamięci (ang. freeing)
//declaration
mpc_t z
// Initialisation
mpc_init2 (z, prec)
//Assignment
mpc_set
//Computation
//Freeing
mpc_clear (z)
Najprostszy przykład:[7]
// gcc foo.c -lmpc
#include "mpc.h"
int main() {
mpc_t x; // declaration
mpc_init2 (x, 256); // Initialisation
// Assignment ( here nothing )
// Computation ( here nothing )
mpc_clear (x); // Freeing
return 0;
}
Kompilacja:
gcc ... -lmpc -lmpfr -lgmp ...
Przykłady
edytuj#include <stdio.h>
#include <gmp.h>
#include <mpfr.h>
#include <mpc.h>
/*
LD_LIBRARY_PATH=/usr/local/include
export LD_LIBRARY_PATH
to compile (from Linux console)
Link your program with libaries : MPC , MPFR and GMP.
MPFR library reference (-lmpfr) should be before GMP's one (-lgmp) :
gcc mpc.c -lmpc -lmpfr -lgmp
and run :
./a.out
*/
int main (void)
{
mpc_t x, y;
mpc_init2 (x, 256); /* precision exactly 256 bits */
mpc_init3 (y, 100, 50); /* 100/50 bits for the real/imaginary part */
mpc_clear (x);
mpc_clear (y);
}
wersja
edytuj/*
gcc m.c -lmpc -mpfr -lgmp -Wall
*/
#include <stdio.h>
#include <gmp.h>
#include <mpfr.h>
#include "mpc.h"
int main() {
mpfr_printf(" MPC-%s \nMPFR-%s \n GMP-%s \n", MPC_VERSION_STRING, mpfr_version, gmp_version );
return 0;
}
Przykładowy wynik
MPC-1.1.0 MPFR-4.0.2 GMP-6.2.0
asin(2i)
edytujFunkcja asin oblicza arcsine z liczby całkowitej:
/*
https://www.gnu.org/ghm/2011/paris/slides/andreas-enge-mpc.pdf
gcc a.c -lmpc -lmpfr -lgmp
*/
#include <stdio.h>
#include <gmp.h>
#include <mpfr.h>
#include <mpc.h>
int main (void) {
mpc_t z; // input value = op
int inex; // return value of the function ( not the result of computation )
mpc_t r; // output value = rop : r=f(z)
mpc_init2 (z, 123);
mpc_init2 (r, 123);
mpc_set_ui_ui (z, 0, 2, MPC_RNDNN); // z = 0 + 2i
//
inex = mpc_asin (r, z, MPC_RNDNN); // r = asin(z)
printf ("asin");
mpc_out_str (stdout, 10, 0, z, MPC_RNDNN);
printf (" = ");
mpc_out_str (stdout, 10, 0, r, MPC_RNDNN);
printf (" \n");
printf ("inex = %i %i\n", MPC_INEX_RE (inex), MPC_INEX_IM (inex));
mpc_clear(z);
mpc_clear(r);
}
Wynik:
asin(0 2.00000000000000000000000000000000000000) = (0 1.44363547517881034249327674027310526938) inex = 0 -1
mpc_set_str
edytuj/*
https://www.gnu.org/ghm/2011/paris/slides/andreas-enge-mpc.pdf
gcc s.c -lmpc -lmpfr -lgmp
*/
#include <stdio.h>
#include <gmp.h>
#include <mpfr.h>
#include <mpc.h>
int DescribeInex(int inex)
{
printf ("inex = %d ; %i %i\n", inex, MPC_INEX_RE (inex), MPC_INEX_IM (inex));
if (inex==-1) printf(" bad input string \n\n") ;
else {if (MPC_INEX_RE (inex)==0) printf(" real part value is exact as the input \n");
if (MPC_INEX_RE (inex)<0) printf(" rounded real part value is less than the exact one input \n");
if (MPC_INEX_RE (inex)>0) printf(" rounded real part value is grater than the exact one input \n");
if (MPC_INEX_IM (inex)==0) printf(" imag part value is exact as the input \n");
if (MPC_INEX_IM (inex)<0) printf(" rounded imag part value is less than the exact one input \n");
if (MPC_INEX_IM (inex)>0) printf(" rounded imag part value is grater than the exact one input \n");
printf(" \n");
}
return 0;
}
int main (void) {
mpc_t z; // input value = op
int inex; // return value of the function ( not the result of computation )
//mpc_t r; // output value = rop : r=f(z)
//
mpc_init2 (z, 123);
//mpc_init2 (r, 123);
// bad input
inex = mpc_set_str (z, "(-1.8605aaa7396001587505e+00 -0.00000093437424500e+00)",10, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 10, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 10, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 10, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex( inex);
// bad input
inex = mpc_set_str (z, "(aa7396001587505e+00 -0.00000ggg093437424500e+00)",10, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 10, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 10, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 10, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex( inex);
// good input
inex = mpc_set_str (z, "(-1.86057396001587505e+00 -0.00000093437424500e+00)",10, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 10, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 10, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 10, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex( inex);
// good input
inex = mpc_set_str (z, "(-1 -0.00000093437424500e+00)",10, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 10, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 10, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 10, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex(inex);
// good binary input
inex = mpc_set_str (z, "0b101",0, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 2, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 2, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 2, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex(inex);
// good binary input ; If base = 0, then a prefix may be used to indicate the base in which the floating-point number is written.
inex = mpc_set_str (z, "(0b101 0b1.01)",0, MPC_RNDNN); // read z value from string
// print result
printf ("z = "); mpc_out_str (stdout, 2, 0, z, MPC_RNDNN); printf (" \n");
printf ("z = "); mpfr_out_str (stdout, 2, 0, mpc_realref (z), MPFR_RNDD); printf (" ; "); mpfr_out_str (stdout, 2, 0, mpc_imagref (z), MPFR_RNDD); printf (" \n ");
DescribeInex(inex);
mpc_clear(z);
//mpc_clear(r);
}