/**********************************************************************
 
	Copyright (C) 2005- Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program 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.

**********************************************************************/

#include	"memory_routine.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"matrix.h"

int mxt_bit_get_size(MATRIX_DATA_TYPE *,void * d);
void * mxt_bit_sexp2md(int * cpy,struct matrix_data_type*,XL_SEXP * s);
XL_SEXP * mxt_bit_md2sexp(struct matrix_data_type*,void * d);
int mxt_bit_cmp(struct matrix_data_type*,void*,void*);
void * mxt_bit_alloc_data(struct matrix_data_type*,int,void*,void*,
			  char*,int);

int mxt_bitv_get_size(MATRIX_DATA_TYPE *,void * d);
int mxt_bitv_cmp(struct matrix_data_type*,void*,void*);
void * mxt_alloc_bitv(MATRIX_DATA_TYPE * tp,int,void * d,void *,
		char*,int);
void
mxt_print_bit(MATRIX_DATA_TYPE*tp,MATRIX_STRING_BUFFER*b,void*d,char*fmt);

MATRIX_DATA_TYPE mx_type_bit = {
	MDT_BIT,
	0,
	mxt_bit_get_size,
	mxt_bit_sexp2md,
	mxt_bit_md2sexp,
	mxt_bit_cmp,
	mxt_vector_copy,
	mxt_alloc_copy,
	mxt_bit_alloc_data,
	mxt_free_data,
	0,0,0,0,
	mxt_endian_nothing,
	mxt_endian_nothing,
	mxt_convert_basic_to_net,
	mxt_convert_basic_to_host,
	0,0,0,0,0,0,0,
	mxt_print_bit,
};

MATRIX_DATA_TYPE mx_type_bit_v = {
	MDT_BIT|MDT_VECTOR,
	&mx_type_bit,
	mxt_bitv_get_size,
	mxt_vector_sexp2md,
	mxt_vector_md2sexp,
	mxt_bitv_cmp,
	mxt_vector_copy,
	mxt_alloc_copy,
	mxt_alloc_bitv,
	mxt_free_data,
	0,0,0,0,
	mxt_endian_nothing,
	mxt_endian_nothing,
	mxt_convert_basic_to_net,
	mxt_convert_basic_to_host,
	0,0,0,0,0,0,0,0
};


int
mxt_bit_get_size(MATRIX_DATA_TYPE * tp,void * d)
{
	return 1;
}


void * 
mxt_bit_sexp2md(int * cpy,struct matrix_data_type* tp,XL_SEXP * s)
{
char * ret;
	if ( get_type(s) != XLT_INTEGER )
		return 0;
	ret = d_alloc(1);
	if ( s->integer.data ) {
		*ret = 1;
	}
	else {
		*ret = 0;
	}
	if ( cpy )
		*cpy = 1;
	return (void*)ret;
}

XL_SEXP * 
mxt_bit_md2sexp(struct matrix_data_type* tp,void * d)
{
char * _d;
	_d = d;
	if ( _d )
		return get_integer(1,0);
	else	return get_integer(0,0);
}

int 
mxt_bit_cmp(struct matrix_data_type* tp,void* d1,void* d2)
{
char * _d1, * _d2;
	_d1 = (char*)d1;
	_d2 = (char*)d2;
	if ( (*_d1) < (*_d2) )
		return -1;
	if ( (*_d1) > (*_d2) )
		return 1;
	return 0; 
}



int
mxt_bitv_get_size(MATRIX_DATA_TYPE * tp,void * d)
{
MATRIX_DATA_HEADER * h;
int i;
int * ix;
int sz;
	h = d;
	ix = (int*)(h+1);
	sz = 1;
	for ( i = 0 ; i < h->dim ; i ++ )
		sz *= ix[i];
	if ( sz % 8 )
		return h->offset + sz / 8 + 1;
	else	return h->offset + sz / 8;
}



int 
mxt_bitv_cmp(struct matrix_data_type* tp,void* d1,void* d2)
{
MATRIX_DH_SET h1;
MATRIX_DH_SET h2;
int ret;
unsigned char * p1, * p2;
int i;
int f;
int r;
	get_matrix_dh_set(&h1,d1);
	get_matrix_dh_set(&h2,d2);
	ret = cmp_dh_set(&h1,&h2);
	if ( ret )
		return ret;
	r = h1.total_element % 8;
	if ( r ) {
		f = 1;
		i = h1.total_element / 8 + 1;
	}
	else {
		f = 0;
	 	i = h1.total_element / 8;
	 }
	for ( p1 = h1.offset , p2 = h2.offset ; i > 0 ; i -- ) {
		if ( i == 1 && f ) {
			r = (1 << r) - 1;
			if ( ((*p1) & r) > ((*p2) & r) )
				return 1;
			if ( ((*p1) & r) < ((*p2) & r) )
				return -1;
		}
		else {
			if ( *p1 > *p2 )
				return 1;
			if ( *p1 < *p2 )
				return -1;
		}
		p1 ++;
		p2 ++;
	}
	return 0;
}


void * 
mxt_bit_alloc_data(struct matrix_data_type* tp,int atype,void* d,void *w,
		char * __f,int __l)
{
char * _d;
char __d;
	_d = (char*)d;
	if ( *_d )
		__d = 1;
	else	__d = 0;
	return xx_mxt_alloc_data(tp,atype,&__d,w,__f,__l);
}

void *
mxt_alloc_bitv(MATRIX_DATA_TYPE * tp,int atype,void * d,void * c,
		char * __f,int __l)
{
MATRIX_ALLOC_VECTOR_PARAM * p;
int header_size;
int offset;
int ix_size;
int total_size;
MATRIX_DATA_HEADER * h;
int * ix;
int i;
char * q, * r;
	p = (MATRIX_ALLOC_VECTOR_PARAM*)d;
	header_size = sizeof(MATRIX_DATA_HEADER)
			+ p->dim * sizeof(int);
	offset = header_size;
	ix_size = 1;
	for ( i = 0 ; i < p->dim ; i ++ )
		ix_size *= p->ix_size[i];
	if ( ix_size % 8 )
		total_size = offset + ix_size / 8 + 1;
	else	total_size = offset + ix_size / 8;
	switch ( atype ) {
	case MD_MMALLOC:
		h = xx_atype_alloc(total_size,atype,gc_text,__f,__l);
		break;
	default:
		h = xx_atype_alloc(total_size,atype,c,__f,__l);
		break;
	}
	h->offset = offset;
	h->type = tp->type;
	h->dim = p->dim;
	ix = (int*)(h+1);
	for ( i= 0 ; i < p->dim ; i ++ )
		ix[i] = p->ix_size[i];
	if ( p->default_data ) {
 		q = ((char*)h) + total_size - offset;
 		r = (char*)p->default_data;
 		if ( *r )
 			memset(q,0,total_size - offset);
 		else	memset(q,0xff,total_size - offset);
	}
	return (void*)h;
}



void
mxt_print_bit(MATRIX_DATA_TYPE*tp,MATRIX_STRING_BUFFER*b,void*d,char*fmt)
{
char buffer[1000];
	if ( fmt == 0 ) {
		sprintf(buffer,"%i",(int)*(char*)d);
	}
	else {
		sprintf(buffer,fmt,*(char*)d);
	}
	out_matrix_string_buffer(b,buffer);
}



