/*
  rb_gsl_common.h
  Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library)
    (C) Copyright 2001-2004 by Yoshiki Tsunesada

  Ruby/GSL is free software: you can redistribute it and/or modify it
  under the terms of the GNU General Public License.
  This library is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef ___RB_GSL_COMMON_H___
#define ___RB_GSL_COMMON_H___

#include "ruby.h"
#include <gsl/gsl_errno.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_complex.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_permutation.h>
#include <gsl/gsl_ieee_utils.h>

EXTERN VALUE mgsl;
EXTERN ID rb_gsl_id_beg, rb_gsl_id_end, rb_gsl_id_excl;

#ifndef CHECK_FIXNUM
#define CHECK_FIXNUM(x) if(!FIXNUM_P(x))rb_raise(rb_eTypeError,"Fixnum expected");
#endif

#ifndef Need_Float
#define Need_Float(x) (x) = rb_Float(x)
#endif

#ifndef Need_Float2
#define Need_Float2(x,y) do {\
    Need_Float(x);\
    Need_Float(y);} while (0)
#endif

#ifndef COMPLEX_P
#define COMPLEX_P(x) (rb_obj_is_kind_of(x,cgsl_complex)?1:0)
#endif

#ifndef CHECK_COMPLEX
#define CHECK_COMPLEX(x) if(!rb_obj_is_kind_of(x,cgsl_complex))\
    rb_raise(rb_eTypeError, "wrong argument type (Complex expected)");
#endif

#ifndef VECTOR_P
#define VECTOR_P(x) (rb_obj_is_kind_of(x,cgsl_vector)?1:0)
#endif

#ifndef VECTOR_ROW_P
#define VECTOR_ROW_P(x) ((CLASS_OF(x)==cgsl_vector||CLASS_OF(x)==cgsl_vector_view)?1:0)
#endif

#ifndef VECTOR_COL_P
#define VECTOR_COL_P(x) ((CLASS_OF(x)==cgsl_vector_col||CLASS_OF(x)==cgsl_vector_col_view)?1:0)
#endif

#ifndef VECTOR_ROW_COL
#define VECTOR_ROW_COL(x) (VECTOR_ROW_P(x)?cgsl_vector:cgsl_vector_col)
#endif

#ifndef CHECK_VECTOR
#define CHECK_VECTOR(x) if(!rb_obj_is_kind_of(x,cgsl_vector))\
    rb_raise(rb_eTypeError, "wrong argument type (Vector expected)");
#endif

#ifndef VECTOR_COMPLEX_P
#define VECTOR_COMPLEX_P(x) (rb_obj_is_kind_of(x,cgsl_vector_complex)?1:0)
#endif

#ifndef VECTOR_COMPLEX_ROW_P
#define VECTOR_COMPLEX_ROW_P(x) ((CLASS_OF(x)==cgsl_vector_complex||CLASS_OF(x)==cgsl_vector_complex_view)?1:0)
#endif

#ifndef VECTOR_COMPLEX_COL_P
#define VECTOR_COMPLEX_COL_P(x) ((CLASS_OF(x)==cgsl_vector_complex_col||CLASS_OF(x)==cgsl_vector_complex_col_view)?1:0)
#endif

#ifndef VECTOR_COMPLEX_ROW_COL
#define VECTOR_COMPLEX_ROW_COL(x) (VECTOR_COMPLEX_ROW_P(x)?cgsl_vector_complex:cgsl_vector_complex_col)
#endif

#ifndef CHECK_VECTOR_COMPLEX
#define CHECK_VECTOR_COMPLEX(x) if(!rb_obj_is_kind_of(x,cgsl_vector_complex))\
    rb_raise(rb_eTypeError, "wrong argument type (Vector::Complex expected)");
#endif

#ifndef MATRIX_P
#define MATRIX_P(x) (rb_obj_is_kind_of(x,cgsl_matrix)?1:0)
#endif

#ifndef CHECK_MATRIX
#define CHECK_MATRIX(x) if(!rb_obj_is_kind_of(x,cgsl_matrix))\
    rb_raise(rb_eTypeError, "wrong argument type (Matrix expected)");
#endif

#ifndef MATRIX_COMPLEX_P
#define MATRIX_COMPLEX_P(x) (rb_obj_is_kind_of(x,cgsl_matrix_complex)?1:0)
#endif

#ifndef CHECK_MATRIX_COMPLEX
#define CHECK_MATRIX_COMPLEX(x) if(!rb_obj_is_kind_of(x,cgsl_matrix_complex))\
    rb_raise(rb_eTypeError, "wrong argument type (Matrix::Complex expected)");
#endif

#ifndef PERMUTATION_P
#define PERMUTATION_P(x) (rb_obj_is_kind_of(x,cgsl_permutation)?1:0)
#endif

#ifndef CHECK_PERMUTATION
#define CHECK_PERMUTATION(x) if(!rb_obj_is_kind_of(x,cgsl_permutation))\
    rb_raise(rb_eTypeError, "wrong argument type (Permutation expected)");
#endif

#ifndef COMBINATION_P
#define COMBINATION_P(x) (rb_obj_is_kind_of(x,cgsl_combination)?1:0)
#endif

#ifndef CHECK_COMBINATION
#define CHECK_COMBINATION(x) if(!rb_obj_is_kind_of(x,cgsl_combination))\
    rb_raise(rb_eTypeError, "wrong argument type (Combination expected)");
#endif

#ifndef PROC_P
#define PROC_P(x) (rb_obj_is_kind_of(x,rb_cProc)?1:0)
#endif

#ifndef CHECK_PROC
#define CHECK_PROC(x) if(!rb_obj_is_kind_of(x,rb_cProc))\
    rb_raise(rb_eTypeError, "wrong argument type (Proc expected)");
#endif

#ifndef FUNCTION_P
#define FUNCTION_P(x) (rb_obj_is_kind_of(x,cgsl_function)?1:0)
#endif

#ifndef CHECK_FUNCTION
#define CHECK_FUNCTION(x) if(!rb_obj_is_kind_of(x,cgsl_function))\
    rb_raise(rb_eTypeError, "wrong argument type (Function expected)");
#endif

#ifndef HISTOGRAM_P
#define HISTOGRAM_P(x) (rb_obj_is_kind_of(x,cgsl_histogram)?1:0)
#endif

#ifndef CHECK_HISTOGRAM
#define CHECK_HISTOGRAM(x) if(!rb_obj_is_kind_of(x,cgsl_histogram))\
    rb_raise(rb_eTypeError, "wrong argument type (Histogram expected)");
#endif

void rb_gsl_error_handler(const char *reason, const char *file,
				 int line, int gsl_errno);

FILE* rb_gsl_open_writefile(VALUE io, int *flag);
FILE* rb_gsl_open_readfile(VALUE io, int *flag);

VALUE rb_gsl_obj_read_only(int argc, VALUE *argv, VALUE obj);

int str_tail_grep(char *s0, char *s1);

#ifdef RUBY_1_8_LATER
#define RB_GSL_MAKE_PROC rb_block_proc()
#else
#define RB_GSL_MAKE_PROC rb_f_lambda()
#endif

#endif
