/* sort.c Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library) (C) Copyright 2001-2006 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. */ #include "include/rb_gsl_array.h" #include #include EXTERN ID RBGSL_ID_call; EXTERN VALUE cgsl_complex; int rb_gsl_comparison_double(const void *aa, const void *bb); int rb_gsl_comparison_complex(const void *aa, const void *bb); int rb_gsl_comparison_double(const void *aa, const void *bb) { double *a = NULL, *b = NULL; a = (double *) aa; b = (double *) bb; return FIX2INT(rb_funcall(rb_block_proc(), RBGSL_ID_call, 2, rb_float_new(*a), rb_float_new(*b))); } int rb_gsl_comparison_complex(const void *aa, const void *bb) { gsl_complex *a = NULL, *b = NULL; a = (gsl_complex *) aa; b = (gsl_complex *) bb; return FIX2INT(rb_funcall(rb_block_proc(), RBGSL_ID_call, 2, Data_Wrap_Struct(cgsl_complex, 0, NULL, a), Data_Wrap_Struct(cgsl_complex, 0, NULL, b))); } static VALUE rb_gsl_heapsort_vector(VALUE obj) { gsl_vector *v = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector, v); gsl_heapsort(v->data, v->size, sizeof(double), rb_gsl_comparison_double); return obj; } static VALUE rb_gsl_heapsort_vector2(VALUE obj) { gsl_vector *v = NULL, *vnew = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector, v); vnew = gsl_vector_alloc(v->size); gsl_vector_memcpy(vnew, v); gsl_heapsort(vnew->data, vnew->size, sizeof(double), rb_gsl_comparison_double); return Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew); } static VALUE rb_gsl_heapsort_index_vector(VALUE obj) { gsl_vector *v = NULL; gsl_permutation *p = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector, v); p = gsl_permutation_alloc(v->size); gsl_heapsort_index(p->data, v->data, v->size, sizeof(double), rb_gsl_comparison_double); return Data_Wrap_Struct(cgsl_permutation, 0, gsl_permutation_free, p); } static VALUE rb_gsl_heapsort_vector_complex(VALUE obj) { gsl_vector_complex *v = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector_complex, v); gsl_heapsort(v->data, v->size, sizeof(gsl_complex), rb_gsl_comparison_complex); return obj; } static VALUE rb_gsl_heapsort_vector_complex2(VALUE obj) { gsl_vector_complex *v = NULL, *vnew = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector_complex, v); vnew = gsl_vector_complex_alloc(v->size); gsl_vector_complex_memcpy(vnew, v); gsl_heapsort(vnew->data, vnew->size, sizeof(gsl_complex), rb_gsl_comparison_complex); return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vnew); } static VALUE rb_gsl_heapsort_index_vector_complex(VALUE obj) { gsl_vector_complex *v = NULL; gsl_permutation *p = NULL; if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); Data_Get_Struct(obj, gsl_vector_complex, v); p = gsl_permutation_alloc(v->size); gsl_heapsort_index(p->data, v->data, v->size, sizeof(gsl_complex), rb_gsl_comparison_complex); return Data_Wrap_Struct(cgsl_permutation, 0, gsl_permutation_free, p); } /* singleton */ static VALUE rb_gsl_heapsort(VALUE obj, VALUE vv) { if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); if (rb_obj_is_kind_of(vv, cgsl_vector_complex)) { return rb_gsl_heapsort_vector_complex(vv); } else if (rb_obj_is_kind_of(vv, cgsl_vector)) { return rb_gsl_heapsort_vector(vv); } else { rb_raise(rb_eTypeError, "wrong argument type %s (Vector or Vector::Complex expected)", rb_class2name(CLASS_OF(vv))); } return vv; } static VALUE rb_gsl_heapsort2(VALUE obj, VALUE vv) { if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); if (rb_obj_is_kind_of(vv, cgsl_vector_complex)) { return rb_gsl_heapsort_vector_complex2(vv); } else if (rb_obj_is_kind_of(vv, cgsl_vector)) { return rb_gsl_heapsort_vector2(vv); } else { rb_raise(rb_eTypeError, "wrong argument type %s (Vector or Vector::Complex expected)", rb_class2name(CLASS_OF(vv))); } return vv; } static VALUE rb_gsl_heapsort_index(VALUE obj, VALUE vv) { if (!rb_block_given_p()) rb_raise(rb_eRuntimeError, "Proc is not given"); if (rb_obj_is_kind_of(vv, cgsl_vector_complex)) { return rb_gsl_heapsort_index_vector_complex(vv); } else if (rb_obj_is_kind_of(vv, cgsl_vector)) { return rb_gsl_heapsort_index_vector(vv); } else { rb_raise(rb_eTypeError, "wrong argument type %s (Vector or Vector::Complex expected)", rb_class2name(CLASS_OF(vv))); } return vv; } /*****/ #ifdef HAVE_NARRAY_H #include "narray.h" static VALUE rb_gsl_sort_narray(VALUE obj) { struct NARRAY *na; size_t size, stride; double *ptr1, *ptr2; VALUE ary; GetNArray(obj, na); ptr1 = (double*) na->ptr; size = na->total; stride = 1; ary = na_make_object(NA_DFLOAT, na->rank, na->shape, CLASS_OF(obj)); ptr2 = NA_PTR_TYPE(ary, double*); memcpy(ptr2, ptr1, sizeof(double)*size); gsl_sort(ptr2, stride, size); return ary; } static VALUE rb_gsl_sort_narray_bang(VALUE obj) { struct NARRAY *na; size_t size, stride; double *ptr1; GetNArray(obj, na); ptr1 = (double*) na->ptr; size = na->total; stride = 1; gsl_sort(ptr1, stride, size); return obj; } static VALUE rb_gsl_sort_index_narray(VALUE obj) { struct NARRAY *na; size_t size, stride; double *ptr1; gsl_permutation *p; GetNArray(obj, na); ptr1 = (double*) na->ptr; size = na->total; stride = 1; p = gsl_permutation_alloc(size); gsl_sort_index(p->data, ptr1, stride, size); return Data_Wrap_Struct(cgsl_permutation, 0, gsl_permutation_free, p); } #endif void Init_gsl_sort(VALUE module) { rb_define_singleton_method(module, "heapsort!", rb_gsl_heapsort, 1); rb_define_singleton_method(module, "heapsort", rb_gsl_heapsort2, 1); rb_define_singleton_method(module, "heapsort_index", rb_gsl_heapsort_index, 1); rb_define_method(cgsl_vector, "heapsort!", rb_gsl_heapsort_vector, 0); rb_define_method(cgsl_vector, "heapsort", rb_gsl_heapsort_vector2, 0); rb_define_method(cgsl_vector, "heapsort_index", rb_gsl_heapsort_index_vector, 0); rb_define_method(cgsl_vector_complex, "heapsort!", rb_gsl_heapsort_vector_complex, 0); rb_define_method(cgsl_vector_complex, "heapsort", rb_gsl_heapsort_vector_complex2, 0); rb_define_method(cgsl_vector_complex, "heapsort_index", rb_gsl_heapsort_index_vector_complex, 0); #ifdef HAVE_NARRAY_H rb_define_method(cNArray, "gsl_sort", rb_gsl_sort_narray, 0); rb_define_method(cNArray, "gsl_sort!", rb_gsl_sort_narray_bang, 0); rb_define_method(cNArray, "gsl_sort_index", rb_gsl_sort_index_narray, 0); #endif }