/*
 * dcl_cary2obj.c
 *   $Id: dcl_cary2obj.c,v 1.3 2000/11/12 00:37:37 keiko Exp $
 */

#include <math.h>
#include "ruby.h"
#include "libtinyf2c.h"
#include "narray.h"  /* kuro: depend on numarray.so */


/*  functions  */
VALUE dcl_ccharary2obj(char *, int, int);
VALUE dcl_cintegerary2obj(integer *, int, int, int *);
VALUE dcl_crealary2obj(real *, int, int, int *);
VALUE dcl_ccomplexary2obj(complex *, int, char *);
VALUE dcl_clogicalary2obj(logical *, int, int, int *);

static VALUE ccharary2ary(char *, int, int);
static VALUE cintegerary2ary(integer *, int);
static VALUE crealary2ary(real *, int);
static VALUE clogicalary2ary(logical *, int);
/* not inplemented
static VALUE ccomplexary2ary(complex *, int);
*/

/* kuro: depend on numarray.so */
static VALUE crealary2na(real *, int, int, int *);
static VALUE clogicalary2na(logical *, int, int, int *);
static VALUE cintegerary2na(integer *, int, int, int *);
/* not implemented
static VALUE ccomplexary2na(complex *, int, char *);
*/


/*
 * dcl_cxxxary2obj() : convert c xxx type array to ruby object
 *   dcl_ccharary2obj()
 *   dcl_cintegerary2obj()
 *   dcl_crealary2obj()
 *   dcl_ccomplexary2obj() : not implemented
 *   dcl_clogicalary2obj()
 */
VALUE
dcl_ccharary2obj(cary, size, len)
    char *cary;
    int size;
    int len;
{
    VALUE obj;

    obj = ccharary2ary(cary, size, len);

    return obj;
}

VALUE
dcl_cintegerary2obj(cary, size, rank, shape)
    integer *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;

    /* if ( rank == 1 ) {
	obj = cintegerary2ary(cary, size);
    } else { */
	obj = cintegerary2na(cary, size, rank, shape);
    /*}*/

    return obj;
}

VALUE
dcl_crealary2obj(cary, size, rank, shape)
    real *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;

    /* if ( rank == 1 ) {
	obj = crealary2ary(cary, size);
    } else { */
	obj = crealary2na(cary, size, rank, shape);
    /*}*/

    return obj;
}

/* not implemented
VALUE
dcl_ccomplexary2obj(cary, size, type)
    complex *cary;
    int size;
    char *type;
{
    VALUE obj;

    if ((type == NULL) || ( *type == '\0' )) {
	obj = ccomplexary2ary(cary, size);
    } else {
	obj = ccomplexary2na(cary, size, type);
    }

    return obj;
}
*/

VALUE
dcl_clogicalary2obj(cary, size, rank, shape)
    logical *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;

    obj = clogicalary2ary(cary, size);

    /*if ( rank == 0) {
	obj = clogicalary2ary(cary, size);
    } else {*/
	obj = clogicalary2na(cary, size, rank, shape);
    /*}*/
    
    return obj;
}


/*
 *  cxxxary2ary() : convert c xxx type array to Array object
 *                  called by cxxxary2obj()
 *   ccharary2ary()
 *   cintegerary2ary()
 *   crealary2ary()
 *   ccomplexary2ary() : not implemented
 *   clogicalary2ary()
 */
static VALUE
ccharary2ary(cary, size, len)
    char *cary;
    int size;
    int len;
{
    VALUE obj, item;
    char *buf, *hd, *ed;
    int i, j;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size/len);
    buf = ALLOCA_N(char, len+1);
    hd = cary;
    for (i = 0; i < size/len; i++) {
        j = len - 1;
        ed = hd + j;
        while ((j >= 0) && (*ed == ' ' || *ed == '\0')) {
            ed--;
            j--;
        }
        if (j >= 0) memcpy(buf, hd, j+1);
        buf[j+1] = '\0';
        item = rb_str_new2(buf);
        rb_ary_push(obj, item);
        hd += len;
    }

    return obj;
}

static VALUE
cintegerary2ary(cary, size)
    integer *cary;
    int size;
{
    VALUE obj, item;
    int i;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size);

    for (i = 0; i < size; i++) {
        item = INT2NUM(cary[i]);
	rb_ary_push(obj, item);
    }

    return obj;
}

static VALUE
crealary2ary(cary, size)
    real *cary;
    int size;
{
    VALUE obj, item;
    int i;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size);

    for (i = 0; i < size; i++) {
	item = rb_float_new((double)cary[i]);
	rb_ary_push(obj, item);
    }

    return obj;
}

/* not inplemented
static VALUE
ccomplexary2ary(cary, size)
    complex *cary;
    int size;
{
    VALUE obj, item;
    int i;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size);

    for (i = 0; i < size; i++) {
	item = ... cary[i];
	rb_ary_push(obj, item);
    }

    return obj;
}
*/

static VALUE
clogicalary2ary(cary, size)
    logical *cary;
    int size;
{
    VALUE obj, item;
    int i;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size);

    for (i = 0; i < size; i++) {
	item = (cary[i] == FALSE_) ? Qfalse : Qtrue;
	rb_ary_push(obj, item);
    }

    return obj;
}


/* kuro: depend on numarray.so */
/*
 *  cxxxary2na() : convert c xxx type array to NumArray object
 *                 called by cxxxary2obj()
 *   cintegerary2na() : not implemented
 *   crealary2na()
 *   ccomplexary2na() : not implemented
 *   clogicalary2na()
 */
static VALUE
crealary2na(cary, size, rank, shape)
    real *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    float *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_SFLOAT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (float *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (float)cary[i];
    }

    return obj;
}

static VALUE
cintegerary2na(cary, size, rank, shape)
    integer *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    int32_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_LINT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (int32_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (int32_t)cary[i];
    }

    return obj;
}

static VALUE
clogicalary2na(cary, size, rank, shape)
    logical *cary;
    int size;
    int rank;
    int *shape;
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    u_int8_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NumArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_BYTE, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (u_int8_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (u_int8_t)cary[i];
    }

    return obj;
}

