/**********************************************************************
 
	Copyright (C) 2003 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.

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


#ifndef ___UNIT_H___
#define ___UNIT_H___

#include	"machine/include.h"
#include	"long_char.h"

#define HASH_UNIT_SIZE	100

#define D_L	0
#define D_T	1
#define D_W	2
#define D_A	3
#define DIM	4

typedef struct dimension {
	unsigned short		u;	/* unit no of system unit */
	short			p;	/* powers */
	int			r;	/* rate */
} DIMENSION;

typedef struct system_unit {
	struct system_unit *	next;
	short			no;
	L_CHAR *		name;
	double			shi;
	double			bo;
	INTEGER64		shi_int;
	INTEGER64		bo_int;
} SYSTEM_UNIT;

typedef struct unit_alias {
	struct unit_alias *	n_next;
	struct unit_alias *	d_next;
	L_CHAR *		name;
	DIMENSION		dim[DIM];
} UNIT_ALIAS;


typedef struct unit_env {
	struct unit_env *	next;
	L_CHAR *		name;
	UNIT_ALIAS * 		name_hash[HASH_UNIT_SIZE];
	UNIT_ALIAS * 		dim_hash[HASH_UNIT_SIZE];
	SYSTEM_UNIT * 		sys_unit[DIM];
	SYSTEM_UNIT ** 		no2su[DIM];
	int 			no2su_len[DIM];
} UNIT_ENV;


typedef struct coordinate_unit {
	struct coordinate_unit *	next;
	L_CHAR *			url;
	L_CHAR *			system;
	L_CHAR *			unit;
	UNIT_ENV *			uenv;
} COORDINATE_UNIT;


double conv_unit(int * er,
	UNIT_ENV*,double inp,L_CHAR * from,L_CHAR * to);
int
conv_unit_integer(int * er,
	UNIT_ENV*,int inp,DIMENSION * _from,DIMENSION * _to);
double
conv_unit_floating(int * er,
	UNIT_ENV *,double inp,DIMENSION * _from,DIMENSION * _to);
void system_unit_alias(UNIT_ENV * ue);
int name2dim(UNIT_ENV *,DIMENSION * dim,L_CHAR *  name);
void zero_unit(DIMENSION * dim);
L_CHAR * dim2name(UNIT_ENV*,DIMENSION * dim);
int n_new_su(UNIT_ENV *,int sys,char * name,double shi,double bo);
int new_su(UNIT_ENV *,int sys,L_CHAR * name,double shi,double bo);
int n_new_ua(UNIT_ENV *,DIMENSION * dim,char * name);
int new_ua(UNIT_ENV *,DIMENSION * dim,L_CHAR * name);
void fit_dimension_integer(DIMENSION * dest,DIMENSION * s1,DIMENSION * s2);
void fit_dimension_floating(DIMENSION * dest,DIMENSION * s1,DIMENSION * s2);
void normalize_dim_floating(UNIT_ENV*,DIMENSION * dim,double * data);
void normalize_dim_integer(UNIT_ENV*,DIMENSION * dim,int * data);
int dim_power_cmp(DIMENSION * d1,DIMENSION * d2);
void print_dim(DIMENSION *);
UNIT_ENV * copy_uenv1(UNIT_ENV * u);
void copy_uenv2(UNIT_ENV * to,UNIT_ENV * from);

void set_uenv_name(UNIT_ENV *,L_CHAR *);
void _set_uenv_name(UNIT_ENV *,L_CHAR *);
void del_uenv_name(L_CHAR *);
void _del_uenv_name(L_CHAR *);
UNIT_ENV * _search_uenv_name(L_CHAR *);
UNIT_ENV * search_uenv_name(L_CHAR *);

void lock_unit();
void unlock_unit();
UNIT_ENV * new_uenv();

void free_c_unit(COORDINATE_UNIT * u);
L_CHAR * reso_c_unit(COORDINATE_UNIT * u);
L_CHAR * reso_c_unit_str(L_CHAR * str);
void zero_c_unit(COORDINATE_UNIT * u);

#endif
