version 1.1, 1999/09/28 21:26:21
|
version 1.13, 2005/02/15 22:15:05
|
Line 1
|
Line 1
|
|
/* functions to handle the unit parser/comparison engine |
|
Copyright (C) 1992-2000 Michigan State University |
|
|
|
The CAPA system is free software; you can redistribute it and/or |
|
modify it under the terms of the GNU General Public License as |
|
published by the Free Software Foundation; either version 2 of the |
|
License, or (at your option) any later version. |
|
|
|
The CAPA system 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. See the GNU |
|
General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public |
|
License along with the CAPA system; see the file COPYING. If not, |
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
Boston, MA 02111-1307, USA. |
|
|
|
As a special exception, you have permission to link this program |
|
with the TtH/TtM library and distribute executables, as long as you |
|
follow the requirements of the GNU GPL in regard to all of the |
|
software in the executable aside from TtH/TtM. |
|
*/ |
|
|
/* =||>|===================== capaUnit.c =====================|<||= */ |
/* =||>|===================== capaUnit.c =====================|<||= */ |
/* created by Isaac Tsai 1997 */ |
/* created by Isaac Tsai 1997 */ |
/* copyrighted by Isaac Tsai 1997, 1998, 1999 */ |
/* by Isaac Tsai 1997, 1998, 1999 */ |
/* =||>|========================================================|<||= */ |
/* =||>|========================================================|<||= */ |
#include <stdio.h> /* fopen() */ |
#include <stdio.h> /* fopen() */ |
#include <stdlib.h> |
#include <stdlib.h> |
#include <ctype.h> /* isalnum() */ |
#include <ctype.h> /* isalnum() */ |
#include <string.h> |
#include <string.h> |
#include <math.h> |
#include <math.h> |
|
#include <float.h> |
|
|
#include "capaParser.h" |
#include "capaParser.h" |
|
|
Line 632 postorder_utree(node_p) Unit_t *node_p;
|
Line 656 postorder_utree(node_p) Unit_t *node_p;
|
return (result); |
return (result); |
} |
} |
|
|
|
/* returns 1 on okay, 2 on error*/ |
int |
int |
postwalk_utree(Unit_t *n_p) |
postwalk_utree(Unit_t *n_p) |
{ |
{ |
Line 640 postwalk_utree(Unit_t *n_p)
|
Line 665 postwalk_utree(Unit_t *n_p)
|
if( n_p == NULL ) return (1); |
if( n_p == NULL ) return (1); |
|
|
result = postwalk_utree(U_LEFT(n_p)); |
result = postwalk_utree(U_LEFT(n_p)); |
if( result ) result = postwalk_utree(U_RIGHT(n_p)); |
if (result !=2) { |
if( result ) { |
if( result ) result = postwalk_utree(U_RIGHT(n_p)); |
switch(U_TYPE(n_p)) { |
if (result !=2) { |
case U_DERIVED: Ptopidx++; Pstack[Ptopidx] = n_p; /* push into stack */ |
if( result ) { |
break; |
switch(U_TYPE(n_p)) { |
case U_CONSTANT: Ptopidx++; Pstack[Ptopidx] = n_p; /* push into stack */ |
case U_DERIVED: Ptopidx++; Pstack[Ptopidx] = n_p; /* push into stack */ |
break; |
break; |
case U_OP_POWER: printf("^"); |
case U_CONSTANT: Ptopidx++; Pstack[Ptopidx] = n_p; /* push into stack */ |
break; |
break; |
case U_OP_TIMES: process_op(U_OP_TIMES); /* process operator */ |
case U_UNKNOWN: result=2; |
break; |
/*push into stack anyway, try to parse rest of tree */ |
case U_OP_PLUS: printf("+"); |
break; |
break; |
case U_OP_POWER: printf("^"); result=2; |
case U_OP_MINUS: printf("-"); |
break; |
break; |
case U_OP_TIMES: process_op(U_OP_TIMES); /* process operator */ |
case U_OP_DIVIDE: process_op(U_OP_DIVIDE); /* process operator */ |
break; |
break; |
case U_OP_PLUS: printf("+"); result=2; |
default: printf("()"); |
break; |
break; |
case U_OP_MINUS: printf("-"); result=2; |
|
break; |
|
case U_OP_DIVIDE: process_op(U_OP_DIVIDE); /* process operator */ |
|
break; |
|
default: printf("()"); result=2; |
|
break; |
|
} |
|
} |
} |
} |
} |
} |
return (result); |
return (result); |
Line 695 process_op(int op)
|
Line 727 process_op(int op)
|
} |
} |
} |
} |
|
|
void |
Unit_t* |
process_utree(Unit_t *t) |
process_utree(Unit_t *t) |
{ |
{ |
Ptopidx=0; |
Ptopidx=0; |
postwalk_utree(t); |
postwalk_utree(t); |
if( Ptopidx == 1 ) { |
if( Ptopidx == 1 ) { |
/* printf("Correctly parsed!\n"); */ |
//fprintf(stderr,"Correctly parsed!\n"); |
printf("Unit:%s\n",Sbuf); |
//fprintf(stderr,"Unit:%s\n",Sbuf); |
simplify_unit(Pstack[Ptopidx]); |
simplify_unit(Pstack[Ptopidx]); |
Pstack[Ptopidx]->u_symbol[0]='\0'; |
//Pstack[Ptopidx]->u_symbol[0]='\0'; |
/*sprintf(Pstack[Ptopidx]->u_symbol,"");*/ |
//fprintf(stderr,Pstack[Ptopidx]->u_symbol,""); |
print_unit_t(Pstack[Ptopidx]); |
print_unit_t(Pstack[Ptopidx]); |
u_find_name(Pstack[Ptopidx]); |
//u_find_name(Pstack[Ptopidx]); |
print_matches(Pstack[Ptopidx]); |
//print_matches(Pstack[Ptopidx]); |
free_utree(t); |
return(Pstack[Ptopidx]); |
|
//free_utree(t); |
} |
} |
|
return(t); |
} |
} |
|
|
/* ============================================================== */ |
/* ============================================================== */ |
Line 727 int check_correct_unit(char *u_symb,Uni
|
Line 761 int check_correct_unit(char *u_symb,Uni
|
int result=UNIT_OK; |
int result=UNIT_OK; |
|
|
#ifdef UNIT_DBUG |
#ifdef UNIT_DBUG |
if ((ufp=fopen("unit.DBUG","a"))==NULL) { fprintf(stderr,"Error: can't open login debug\n"); return; } |
if ((ufp=fopen("unit.DBUG","a"))==NULL) { fprintf(stderr,"Error: can't open login debug\n"); return UNIT_FAIL; } |
#endif |
#endif |
|
|
while( isspace(*u_symb) ) u_symb++; |
while( isspace(*u_symb) ) u_symb++; |
|
/* <= change this to search from the end of string */ |
|
/* or to get rid of all the white spaces */ |
|
|
|
|
ap = parse_unit_expr(u_symb); |
ap = parse_unit_expr(u_symb); |
Ptopidx=0; |
Ptopidx=0; |
postwalk_utree(ap); |
|
|
if (postwalk_utree(ap)==1) { |
#ifdef UNIT_DBUG |
#ifdef UNIT_DBUG |
fprintf(ufp,"Ptopidx %d\n",Ptopidx); |
fprintf(ufp,"Ptopidx %d\n",Ptopidx); |
#endif |
#endif |
if( Ptopidx == 1 ) { |
if( Ptopidx == 1 ) { |
simplify_unit(Pstack[Ptopidx]); |
simplify_unit(Pstack[Ptopidx]); |
|
|
if( (Pstack[Ptopidx]->u_count != 0) || |
if( (Pstack[Ptopidx]->u_count != 0) || |
(Pstack[Ptopidx]->u_count == t->u_count) ) { /* has unit */ |
(Pstack[Ptopidx]->u_count == t->u_count) ) { /* has unit */ |
*scale = units_ratio(Pstack[Ptopidx], t); |
*scale = units_ratio(Pstack[Ptopidx], t); |
if( *scale == 0.0 ) { |
if( *scale == 0.0 ) { |
result = UNIT_FAIL; |
result = UNIT_IRRECONCIBLE; |
|
} |
|
free_utree(ap); |
|
} else { |
|
result = UNIT_INVALID_STUDENT3; |
} |
} |
free_utree(ap); |
} else { /* invalid unit representation */ |
} else { |
result = UNIT_INVALID_STUDENT2; |
result = UNIT_FAIL; |
|
} |
} |
} else { /* invalid unit representation */ |
} else { |
result = UNIT_FAIL; |
result = UNIT_INVALID_STUDENT1; |
} |
} |
#ifdef UNIT_DBUG |
#ifdef UNIT_DBUG |
fclose(ufp); |
fclose(ufp); |
Line 856 u_copy_unit(Unit_t *a_p, Unit_t *b_p, do
|
Line 898 u_copy_unit(Unit_t *a_p, Unit_t *b_p, do
|
a_p->u_scale = a_p->u_scale * scale; |
a_p->u_scale = a_p->u_scale * scale; |
/* printf("Found scale=%g=%g\n",a_p->u_scale,b_p->u_scale); */ |
/* printf("Found scale=%g=%g\n",a_p->u_scale,b_p->u_scale); */ |
} else { |
} else { |
if( b_p->u_type == U_BASE || b_p->u_type == U_DERIVED) { |
if( b_p->u_type == U_BASE ) { |
/* *b_p is a base unit, so create a one element unit */ |
/* *b_p is a base unit, so create a one element unit */ |
ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E)); /* *** */ |
ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E)); /* *** */ |
ne_p->ue_scale = b_p->u_scale; |
ne_p->ue_scale = b_p->u_scale; |
Line 870 u_copy_unit(Unit_t *a_p, Unit_t *b_p, do
|
Line 912 u_copy_unit(Unit_t *a_p, Unit_t *b_p, do
|
} |
} |
last_p = ne_p; |
last_p = ne_p; |
a_p->u_count++; |
a_p->u_count++; |
|
} else if( b_p->u_type == U_DERIVED) { |
|
/* derived units but without any units elements (scalar) */ |
|
/*a_p->u_count++;*/ |
|
scale = pow(b_p->u_scale, exp_scale); |
|
a_p->u_scale = a_p->u_scale * scale; |
} else if( b_p->u_type == U_CONSTANT ) { |
} else if( b_p->u_type == U_CONSTANT ) { |
scale = pow(b_p->u_scale, exp_scale); |
scale = pow(b_p->u_scale, exp_scale); |
a_p->u_scale = a_p->u_scale * scale; |
a_p->u_scale = a_p->u_scale * scale; |
Line 1363 u_insert_derived(n_p,s_p,c_p,u_p)char *
|
Line 1410 u_insert_derived(n_p,s_p,c_p,u_p)char *
|
strcpy(new_p->u_comment,c_p); |
strcpy(new_p->u_comment,c_p); |
|
|
simplify_unit(new_p); |
simplify_unit(new_p); |
|
#ifdef UNIT_DBUG |
/* print_unit_t(new_p); */ |
printf("Derived Unit:%s\n",new_p->u_name); |
|
print_unit_t(new_p); |
|
#endif |
if (c_result < 0 ) { |
if (c_result < 0 ) { |
new_p->u_left = t->u_left; new_p->u_right = t; |
new_p->u_left = t->u_left; new_p->u_right = t; |
t->u_left = NULL; |
t->u_left = NULL; |
Line 1411 simplify_unit(u_p) Unit_t *u_p;
|
Line 1459 simplify_unit(u_p) Unit_t *u_p;
|
CScale[ii] = 0.0; |
CScale[ii] = 0.0; |
CExp[ii] = 0.0; |
CExp[ii] = 0.0; |
} |
} |
|
/* |
|
printf("Before Simplify:: \n"); |
|
print_unit_t(u_p); |
|
*/ |
if( u_p->u_count > 0 ) { |
if( u_p->u_count > 0 ) { |
|
|
for(eu_p=u_p->u_list; eu_p; eu_p = eu_p->ue_nextp) { |
for(eu_p=u_p->u_list; eu_p; eu_p = eu_p->ue_nextp) { |
Line 1422 simplify_unit(u_p) Unit_t *u_p;
|
Line 1474 simplify_unit(u_p) Unit_t *u_p;
|
CScale[idx] = CScale[idx] * eu_p->ue_scale; |
CScale[idx] = CScale[idx] * eu_p->ue_scale; |
CExp[idx] = CExp[idx] + eu_p->ue_exp; |
CExp[idx] = CExp[idx] + eu_p->ue_exp; |
} |
} |
/* |
/* debugging |
for(ii=0;ii<BaseUnitcnt;ii++) { |
for(ii=0;ii<BaseUnitcnt;ii++) { |
if( CScale[ii] != 0.0 ) { |
if( CScale[ii] != 0.0 ) { |
printf("(%d)%s,S=%g,E=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]); |
printf("(%d)%s,S=%g,E=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]); |
} |
} |
|
if( CExp[ii] == 0.0 ) { |
|
printf("(%d)%s,S=%g,Exp=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]); |
|
} |
} |
} |
*/ |
*/ |
freelist_unit_e(u_p->u_list); |
freelist_unit_e(u_p->u_list); |
Line 1448 simplify_unit(u_p) Unit_t *u_p;
|
Line 1503 simplify_unit(u_p) Unit_t *u_p;
|
u_p->u_count++; |
u_p->u_count++; |
} |
} |
} |
} |
|
|
|
|
} |
} |
|
/* |
|
printf("After Simplify:: \n"); |
|
print_unit_t(u_p); |
|
*/ |
} |
} |
|
|
/* before comparing two units, make sure they are of basic form */ |
/* before comparing two units, make sure they are of basic form */ |
Line 1688 p_new_unit(Unit_t *left_p, Unit_t *right
|
Line 1744 p_new_unit(Unit_t *left_p, Unit_t *right
|
} else { /* unit *tmp_str not found */ |
} else { /* unit *tmp_str not found */ |
/* printf(" not found\n"); */ |
/* printf(" not found\n"); */ |
err_code = 3; |
err_code = 3; |
|
cu_p->u_type = U_UNKNOWN; |
} |
} |
} else { |
} else { /* symb_str is not in <prefix><units> form */ |
/* printf("<<%s>>", symb_str); */ |
/* printf("<<%s>>", symb_str); */ |
err_code = 2; |
err_code = 2; |
|
cu_p->u_type = U_UNKNOWN; |
} |
} |
} else {/* len == 1 */ |
} else {/* len == 1 */ |
/* printf(" not found\n"); */ |
/* printf(" not found in symbol tree \n"); */ |
err_code = 1; |
err_code = 1; |
|
cu_p->u_type = U_UNKNOWN; |
} |
} |
} |
} |
} else { |
} else { /* why would we have a length less than zero symb_str ? */ |
err_code = 4; |
err_code = 4; |
} |
} |
|
|