[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2 Usando a Biblioteca

Esse capítulo descreve como compilar programas que usam a GSL, e apresenta as convenções usadas na GSL.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.1 Um Programa exemplo

O seguinte programa curto demonstra o uso da biblioteca para cálculo computacional do valor da função de Bessel J_0(x) para x=5,

#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>

int
main (void)
{
  double x = 5.0;
  double y = gsl_sf_bessel_J0 (x);
  printf ("J0(%g) = %.18e\n", x, y);
  return 0;
}

A saída é mostrada abaixo, e deve estar correta para exatidão de precisão dupla,(4)

J0(5) = -1.775967713143382920e-01

Os passos necessários para compilar esse programa são descritos nas seções seguintes.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.2 Compilando e Linkando

Os arquivos de cabeçalho da biblioteca estão instalados no seu próprio diretório ‘gsl’. Você deve escrever qualquer declaração “include” ao pré-processador com um prefixo ‘gsl/’ indicativo de diretório dessa forma,

#include <gsl/gsl_math.h>

Se o diretório gsl não estiver instalado no caminho padrão de busca de seu compilador você também irá precisar fornece a localização desse mesmo diretório gsl ao pré-processador como um sinalizador de linha de comando. A localização padrão do diretório ‘gsl’ é ‘/usr/local/include/gsl’. Um comando típico de compilação para um arquivo fonte ‘example.c’ com o compilador C GNU gcc é,

$ gcc -Wall -I/usr/local/include -c example.c

Isso resulta em um arquivo objeto ‘example.o’. O caminho padrão automático de busca da diretiva include para o gcc é ‘/usr/local/include’ de forma que a opção -I pode ser omitida quando GSL for instalada em sua localização padrão.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.2.1 Linkando programas com a biblioteca

A biblioteca está instalada como um arquivo único, ‘libgsl.a’. Uma versão compartilhada da biblioteca ‘libgsl.so’ está também instalada em sistemas que suportarem bibliotecas compartilhadas. A localização padrão desses arquivos é ‘/usr/local/lib’. Se esse diretório não estiver no caminho padrão de busca de seu linkador você também irá precisar fornecer sua localização como um sinalizador de linha de comando.

Para linkar usando a biblioteca você precisa especificar ambas a biblioteca principal e uma biblioteca que fornece o CBLAS, a qual fornece subrotinas básicas de álgebra linear. Uma adequada implementação da CBLAS é fornecida na biblioteca ‘libgslcblas.a’ se seu sistema não fonecer uma. O seguinte exemplo mostra como linkar uma aplicação com a biblioteca cblas,

$ gcc -L/usr/local/lib example.o -lgsl -lgslcblas -lm

O caminho padrão de busca do gcc procura no diretório ‘/usr/local/lib’ automaticamente de forma que a opção -L pode ser omitida quando a GSL está instalada na sua localização padrão.

A opção -lm linka com a biblioteca matemática do sistema. Em alguns sistemas a opção -lm não é necessária.(5)

Para uma introcução sobre o compilador C GNU e programas relacionados, veja An Introdução to GCC (ISBN 0954161793).(6)


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.2.2 Linkando com uma biblioteca BLAS alternativa

A seguinte linha de comando mostra como você deve linkar a mesma aplicação com uma biblioteca CBLAS alternativa chamada ‘libcblas.a’,

$ gcc example.o -lgsl -lcblas -lm

Para maior desempenho uma biblioteca CBLAS otimizada de forma específica para sua plataforma deve ser usada e estar acessível em -lcblas. A biblioteca deve respeitar as regras da CBLAS padrão. O pacote ATLAS fornece uma biblioteca BLAS de alto desempenho com uma interface CBLAS. O pacote ATLAS é software livre e pode ser instalado para qualquer trabalho que precise de operações rápidas envolvendo vetores e matrizes. A seguinte linha de comando irá linkar com a biblioteca ATLAS e a interface CBLAS que a acompanha,

$ gcc example.o -lgsl -lcblas -latlas -lm

Se a biblioteca ATLAS for instalada em um diretório personalizado use a opção -L para adicionar esse diretório personalizado ao caminho de busca, como descrito acima.

Para mais informações sobre as funções BLAS veja Suporte a BLAS.

O programa gsl-config fornece informações sobre a versão local da biblioteca GSL. Por exemplo, o comando adiante mostra que a biblioteca foi instalada no diretório ‘/usr/local’,

$ gsl-config --prefix
/usr/local

Informações adicionais estão disponíveis usando o comando gsl-config --help.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.3 Bibliotecas Compartilhadas

Para executar um programa linkado com a versão compartilhada da biblioteca o sistema instalado deve estar capacitado a localizar o arquivo ‘.so’ correspondente durante a execução. Se a biblioteca não puder ser encontrada, o seguinte erro irá ocorrer:

$ ./a.out 
./a.out: error while loading shared libraries: 
libgsl.so.0: cannot open shared object file: No such 
file or directory

Para evitar esse erro, ou modifique a configuração de linkagem dinâmica do sistema(7) ou defina a variável de ambiente LD_LIBRARY_PATH de forma a incluir o diretório onde a biblioteca está instalada.

Por exemplo, no shell do tipo Bourne (/bin/sh ou /bin/bash), o caminho de busca de biblioteca pode ser ajustado com os seguinte comandos:

$ LD_LIBRARY_PATH=/usr/local/lib
$ export LD_LIBRARY_PATH
$ ./example

No C-shell (/bin/csh ou /bin/tcsh) o comando equivalente é,

% setenv LD_LIBRARY_PATH /usr/local/lib

O prompt padrão para o C-shell no exemplo acima é o caractere de porcentagem ‘%’, e não deve ser digitado como parte do comando.

Para evitar redigitação desses comandos a cada sessão eles podem ser colocados em um arquivo de login individual ou para todos os usuários (8).

Para compilar uma versão linkada na forma estática do programa, use o sinalizador -static no gcc,

$ gcc -static example.o -lgsl -lgslcblas -lm

[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.4 Obediência ao ANSI C

A biblioteca está escrita em ANSI C e está intencionalmente de acordo com o ANSI C standard (C89). A biblioteca deve ser portável para qualquer sistema com um compilador ANSI C trabalhando. A biblioteca não confia em qualquer extensões não ANSI e nem tampouco na interface que a extensão não ANSI exporta para o usuário. Programas que você escreve usando GSL devem ser obedientes ao padrão ANSI. Extensões que podem ser usadas de uma forma compatível com ANSI C puro são suportados, todavia, através de compilação condicional. Isso permite que a biblioteca aproveite as vantagens de extensões de compilação naquelas plataformas que a suportarem.

Quando um recurso ANSI C é sabidamente falho em um sistema em particular a biblioteca irá excluí-lo de qualquer funções relacionadas no ato de compilação. Esse comportamento torna impossível linkar um programa que deva usar essas funções e fornecer resultados incorretos.

Para evitar conflitos de “namespace” todos os nomes de funções e variáveis exportadas possuem o prefixo gsl_, enquanto que macros exportadas possuem o prefixo GSL_.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.5 Funções Inline

A palavra chave inline não é integrante do padrão ANSI C original (C89) de forma que a biblioteca não exporta quaisquer definições de função da inline por padrão. As funções inline foram introduzidas oficialmente no mais recente padrão C99 mas a maioria dos compiladores C89 possuem também incluído inline como uma extensão já faz muito tempo.

Para permitir o uso das funções inline, a biblioteca fornece versões opcionais da inline de rotinas de desempenho crítico através de compilação condicional nos arquivo de cabeçalho exportados. As versões da inline dessas funções podem ser incluídas através da definição da macro HAVE_INLINE ao se compilar uma aplicação,

$ gcc -Wall -c -DHAVE_INLINE example.c

Se você usa autoconf essa macro pode ser definida automaticamente. Se você não define a macro HAVE_INLINE então as versões lentas não preparadas para usar os recursos das funções inline irão ser usadas ao invés das funções inline.

Por padrão, a forma atual da palavra chave inline é extern inline, a qual é uma extensão gcc que elimina definições desnecessárias de funções. Se a forma extern inline causar problemas com outros compiladores um teste rigoroso de autoconf pode ser usado, veja Macros Autoconf.

Ao compilar com gcc no modo C99 (gcc -std=c99) os arquivos de cabeçalho automaticamente alternam para o modo de declarações de funções inline compatível com o C99 ao invés de extern inline. Com outros compiladores C99, defina a macro GSL_C99_INLINE para usar essas declarações.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.6 Long double

Em geral, os algoritmos na biblioteca foram escritos para somente precisão dupla. O tipo long double (9) não é suportado pelo código fonte da GSL atualmente escrito.

Uma razão para essa escolha é que a exatidão de long double é dependente da plataforma. O padrão IEEE somente especifica a precisão mínima dos números de precisão extendida, enquanto a precisão de double é a mesma em todas as plataformas.

Todavia, números de precisão extendida são necessários algumas vezes para interagir com dados externos no formato long-double, de forma que tipos de dados vetores e matrizes incluem versões com suporte ao tipo de dado long-double.

Esse suporte ao tipo de dado long-double pode ser notado em algumas bibliotecas de sistema como a stdio.h na qual as funções de entrada/saída formatada printf e scanf não estão implementadas corretamente para o tipo de dado long double. Resultados incorretos ou indefinidos são evitados através de testes feitos sobre essas funções de entrada/saída durante o estágio configure da compilação da biblioteca e eliminando certas funções GSL as quais dependem dessa implementação inadequada se for necessário. A correspondente linha na saída do configure assemelha-se ao seguinte,

checking whether printf works with long double... no

consequentemente quando entradas/saídas formatadas do tipo long double não trabalham sobre um dado sistema pode ser impossível linkar um programa que usa funções GSL dependentes dessa implementação incorreta.

Se a linkagem for necessária para trabalhar sobre um sistema que não suporta entrada/saída formatada de long double então as opções são usar formatos binários ou converter resultados long double em resultados double em casos de leitura e escrita.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.7 Funções de portabilidade

Para ajudar na escrita de aplicações portáveis a GSL fornece algumas implementações de funções que são encontradas em outras biblioteca, tais como a biblioteca matemática BSD. Você pode escrever sua aplicação para usar as versões nativas dessas funções, e substituir as versões da GSL por meio de uma macro de pré-processador ou pode usar as versões da GSL se elas estiverem indisponíveis sobre outra plataforma.

Por exemplo, após determinar se a função BSD hypot está disponível você pode incluir as seguintes definições de macro em um arquivo ‘config.h’ com sua aplicação,

/* Utiliza a gsl_hypot pois a hypot não existe no sistema */

#ifndef HAVE_HYPOT
#define hypot gsl_hypot
#endif

O código fonte da aplicação pode então usar o comando include #include <config.h> para substituir cada ocorrência de hypot por gsl_hypot quando hypot não estiver disponível. Essa substituição pode ser feita automaticamente se você usar autoconf, veja Macros Autoconf.

Na maioria das circunstâncias a melhor estratégia é usar as versões nativas dessas funções quando estiverem disponíveis, e voltar às versões equivalentes da GSL em caso contrário, uma vez que usar as funções nativas permite que sua aplicação aproveite quaisquer otimizações específicas para sua plataforma existentes biblioteca do sistema. Essa é a estratégia usada dentro da GSL propriamente dita.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.8 Funções otimizadas alternativas

A implementação principal de algumas funções na biblioteca não irá ser ótima em todas as arquiteturas (10). Por exemplo, existe muitas formas para calcular valores numéricos de uma variável aleatória de Gauss e suas velocidades de execução relativas do algoritmo computacional são dependentes da plataforma. Em casos como esse a biblioteca fornece implementações alternativas dessas funções com a mesma interface. Se você escreve suas aplicações usando chamadas para a implementação padrão você pode selecionar uma versão alternativa mais tarde por meio de uma diretiva de pré-processador. Através de diretivas ao pré-processador também é possível introduzir suas próprias funções otimizadas enquanto garante a portabilidade. As seguintes linhas demonstram o uso de uma escolha dependente da plataforma de métodos para amostragem de uma distribuição de Gauss,

#ifdef SPARC
#define gsl_ran_gaussian gsl_ran_gaussian_ratio_method
#endif
#ifdef INTEL
#define gsl_ran_gaussian my_gaussian
#endif

Essas linhas podem ser colocadas no arquivo de cabeçalho de configuração ‘config.h’ da aplicação, o qual deve então ser incluído por meio de todos os arquivos fonte. Note que as implementações alternativas não irão produzir resultados idênticos bit-a-bit, e no caso de distribuição de números aleatórios irão produzir um fluxo inteiramente diferente de valores numéricos aleatórios.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.9 Suporte a diferentes tipos numéricos

Muitas funções na biblioteca são definidas para diferentes tipos numéricos. Esse recursos é implementado por meio da modificação do nome da função com um modificador relacionado ao tipo de dado numérico—uma forma primitiva da template do C++. O modificador é inserido dentro do nome da função após o prefixo inicial de módulo. A tabela seguinte mostra os nomes de função definidos para todos os tipos numéricos de um módulo imaginário gsl_foo com função fn,

gsl_foo_fn               double        
gsl_foo_long_double_fn   long double   
gsl_foo_float_fn         float         
gsl_foo_long_fn          long          
gsl_foo_ulong_fn         unsigned long 
gsl_foo_int_fn           int           
gsl_foo_uint_fn          unsigned int  
gsl_foo_short_fn         short         
gsl_foo_ushort_fn        unsigned short
gsl_foo_char_fn          char          
gsl_foo_uchar_fn         unsigned char 

A precisão numérica normal double é considerada padrão e não precisa de sufixo. Por exemplo, a função gsl_stats_mean calcula a média entre números de precisão dupla, enquanto a função gsl_stats_int_mean calcula a média entre inteiros.

Um esquema correspondente é usado para tipos definidos da biblioteca, tais como gsl_vector e gsl_matrix. Nesse caso o modificador é anexado ao final do nome do tipo. Por exemplo, se um módulo define um novo tipo de estrutura dependente do tipo ou typedef gsl_foo essa typedef é modificada por outros tipos na seguinte forma,

gsl_foo                  double        
gsl_foo_long_double      long double   
gsl_foo_float            float         
gsl_foo_long             long          
gsl_foo_ulong            unsigned long 
gsl_foo_int              int           
gsl_foo_uint             unsigned int  
gsl_foo_short            short         
gsl_foo_ushort           unsigned short
gsl_foo_char             char          
gsl_foo_uchar            unsigned char 

Quando um módulo contém definições dependentes do tipo de dado a biblioteca fornece cabeçalhos individuais para cada tipo. Os nomes de arquivo são modificados como mostrado abaixo. Por conveniencia o cabeçalho padrão inclui as definições para todos os tipos. Para incluir somente o arquivo de cabeçalho da dupla precisão, ou qualquer outro cabeçalho de algum tipo de dado específico, use seu nome de arquivo correspondente ao nome do tipo de dado desejado.

#include <gsl/gsl_foo.h>               All types
#include <gsl/gsl_foo_double.h>        double        
#include <gsl/gsl_foo_long_double.h>   long double   
#include <gsl/gsl_foo_float.h>         float         
#include <gsl/gsl_foo_long.h>          long          
#include <gsl/gsl_foo_ulong.h>         unsigned long 
#include <gsl/gsl_foo_int.h>           int           
#include <gsl/gsl_foo_uint.h>          unsigned int  
#include <gsl/gsl_foo_short.h>         short         
#include <gsl/gsl_foo_ushort.h>        unsigned short
#include <gsl/gsl_foo_char.h>          char          
#include <gsl/gsl_foo_uchar.h>         unsigned char 

[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.10 Compatibilidade com o C++

Os arquivos de cabeçalho da biblioteca automaticamente definem funções tendo linkagem extern "C" quando a biblioteca é incluída em programas C++. Isso permite que as funções sejam chamadas diretamente a partir do programa em C++.

Para usar o controle de exceção C++ dentro de funções definidas pelo usuário informadas à biblioteca como parâmetros, a biblioteca deve ser construída com a inclusão no sinalizador adicional de compilação CFLAGS da opção ‘-fexceptions’.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.11 Nomes alternativos para vetores estáticos

A biblioteca assume que vetores estáticos, vetores e matrizes informadas como argumentos modificáveis não podem ter nomes alternativos e não se sobrepõem a outros. Isso remove a necessidade de a biblioteca tratar sobreposição de regiões de memória como um caso especial, e permite que otimizações adicionais sejam usadas. Se sobreposição de regiões de memória forem informadas como argumentos modificáveis então os resultados de tais funções irá ser indefinido. Se os argumentos não forem ser modificados (por exemplo, se um protótipo de função declara os argumentos como sendo do tipo const) então sobreposição ou nomes alternativos de regiões de memória podem ser seguramente usados.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.12 Segurança em Linha de Execução

A biblioteca pode ser usada em programas com suporte a linhas de execução multiplas. Todas as funções oferecem suporte a linha de execução segura, no sentido que elas não usam variáveis estáticas. Memória está sempre associada a objetos e não a funções. Para funções que usam objetos workspace como armazenamento temporário os espaços de trabalho (workspace) devem ser alocados sobre uma base de linha de execução. Para funções que usam objetos table como memória só para leitura as tabelas podem ser usadas através de multiplas linhas de execução simultâneamente. Argumentos de tabela são sempre declarados const em protótipos de função, para indicar que eles podem ser seguramente acessados através de diferentes linhas de execução.

Existe um pequeno números de variáveis estáticas globais as quais são usadas para controlar o comportamento geral da biblioteca GSL (e.g. se usar verificação de intervalo, a função a ser chamada em caso de erro grave, etc). Essas variáveis são ajustadas diretamente pelo usuário, de forma que elas devem ser inicializadas uma única vez no início do programa e não são modificadas por diferentes linhas de execução.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.13 Funções Desatualizadas

De tempos em tempos, pode ser necessário que as definições de algumas funções sejam alteradas ou mesmo que as funções sejam removidas da biblioteca. Nessas circunstâncias as funções irão primeiramente ser declaradas desatualizadas e então removidas nas versões subsequêntes da biblioteca. Funções que estão marcadas como de uso não recomendado podem ser desabilitadas na versão corrente por meio do ajuste da diretiva ao pré-processador GSL_DISABLE_DEPRECATED. Esse ajuste permite que o código existente seja testado no que diz respeito a compatibilidades futuras.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

2.14 Reproveitamento do Código

Quando possível as rotinas na biblioteca foram escritas de forma a evitar dependências entre módulos e arquivos. Essa indepedência entre módulos e arquivos deve possibilitar a extração de funções individuais para uso em sua própria aplicação, sem precisar ter a biblioteca completa instalada. Você pode precisar definir certas macros tais como GSL_ERROR e remover alguma declaração #include com o objetivo de compilar os arquivos unidades independentes. A reutilização de código da biblioteca desse modo é encorajado, respeitando os termos da Licença Pública Geral GNU.


[ << ] [ >> ]           [Topo] [Conteúdo] [Índice] [ ? ]

Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.