00001 #include <citrus/config.h>
00002
00003 #include <stdio.h>
00004 #include <math.h>
00005
00006 #include <glib.h>
00007
00008 #include <stdexcept>
00009
00010 #include <citrus/Dimension.H>
00011 #include <citrus/DimensionGroup.H>
00012 #include <citrus/UnitExpr.H>
00013 #include <citrus/Prefix.H>
00014 #include <citrus/Unit.H>
00015
00016
00017 #define yy_create_buffer up_create_buffer
00018 #define yy_delete_buffer up_delete_buffer
00019 #define yy_scan_buffer up_scan_buffer
00020 #define yy_scan_string up_scan_string
00021 #define yy_scan_bytes up_scan_bytes
00022 #define yy_flex_debug up_flex_debug
00023 #define yy_init_buffer up_init_buffer
00024 #define yy_flush_buffer up_flush_buffer
00025 #define yy_load_buffer_state up_load_buffer_state
00026 #define yy_switch_to_buffer up_switch_to_buffer
00027 #define yyin upin
00028 #define yyleng upleng
00029 #define yylex uplex
00030 #define yyout upout
00031 #define yyrestart uprestart
00032 #define yytext uptext
00033 #define yywrap upwrap
00034
00035 #include <citrus/lex.H>
00036 #include "upParser.hh"
00037 #include <citrus/Quantity.H>
00038
00039 extern FILE* upin ;
00040 extern FILE* upout ;
00041 extern int upparse() ;
00042 extern YYSTYPE uplval ;
00043 extern Quantity* theResult ;
00044
00045
00046
00047
00048
00049
00050
00051
00076 void Quantity::eval( UnitExpr* e,
00077 vector<UnitPower>& upwr,
00078 vector<DimensionPower>& dpwr,
00079 double& s )
00080 {
00081 p_eval( e, 1, upwr, dpwr, s ) ;
00082
00083
00084 }
00085
00091 void Quantity::p_eval( UnitExpr* e,
00092 int x,
00093 vector<UnitPower>& upwr,
00094 vector<DimensionPower>& dpwr,
00095 double& s )
00096 {
00097 UnitUnitInfo* ui ;
00098 UnitOperInfo* oi ;
00099 DimensionGroup* dgrp ;
00100 DimensionPower dp ;
00101 vector<DimensionPower>::iterator dm ;
00102 vector<UnitPower>::iterator un ;
00103
00104 switch (e->m_i->type()) {
00105 case UnitInfo::UNIT:
00106 ui = (UnitUnitInfo*)e->m_i ;
00107
00108 if ( ui->m_u ) {
00109 double dscale = 1.0 ;
00110 if ( ui->m_p )
00111 dscale *= pow(10, ui->m_p->exp() ) ;
00112 dscale *= ui->m_u->scale() ;
00113 s *= pow( dscale , x*ui->exp() ) ;
00114
00115 if ( ui->m_u != Unit::dimensionless() ) {
00116 un = find_unit( ui->m_u, upwr ) ;
00117 if ( un != upwr.end() ) {
00118 un->m_pwr += ui->exp()*x ;
00119 if ( un->m_pwr == 0 )
00120 upwr.erase( un ) ;
00121 } else {
00122 upwr.push_back( UnitPower( ui->m_u, ui->m_p, ui->exp()*x ) ) ;
00123 }
00124 dgrp = ui->m_u->dgrp() ;
00125 vector<DimensionPower>::iterator iter = dgrp->m_dims.begin() ;
00126 while ( iter != dgrp->m_dims.end() ) {
00127 dp = *iter ;
00128 dm=find_dimn(dp.m_dim,dpwr) ;
00129 if ( dm != dpwr.end() ) {
00130 dm->m_pwr += dp.m_pwr*ui->exp()*x ;
00131 if ( dm->m_pwr == 0 )
00132 dpwr.erase( dm ) ;
00133 } else {
00134 dpwr.push_back( DimensionPower(dp.m_dim, dp.m_pwr*ui->exp()*x));
00135 }
00136 ++iter ;
00137 }
00138 }
00139 }
00140 break ;
00141 case UnitInfo::OPER:
00142 oi = (UnitOperInfo*)e->m_i ;
00143 if (e->left())
00144 p_eval( e->left(), x, upwr, dpwr, s ) ;
00145 if (e->right())
00146 p_eval( e->right(), oi->op()=='/' ? -1*x : x, upwr, dpwr, s ) ;
00147 break ;
00148 }
00149 return ;
00150 }
00151
00157 Quantity::Quantity()
00158 {
00159 m_val = dtNaN ;
00160 m_dimn.push_back( DimensionPower( find_dsym('1'), 1 ) ) ;
00161 m_units.push_back( UnitPower( Unit::dimensionless(), 0, 1 ) ) ;
00162 m_dgrp = Unit::dimensionless()->dgrp() ;
00163 m_scale = 1.0 ;
00164 }
00165
00168 Quantity::Quantity( const Quantity& qty )
00169 {
00170 m_val = qty.m_val ;
00171 m_dimn = qty.m_dimn ;
00172 m_units = qty.m_units ;
00173 m_dgrp = qty.m_dgrp ;
00174 m_scale = qty.m_scale ;
00175 }
00176
00182 Quantity::Quantity( const char* dimNum )
00183 {
00184 if (theResult)
00185 delete theResult ;
00186
00187
00188 int tlen = strlen(dimNum) ;
00189 char* tmp = new char[tlen+2] ;
00190 strcpy( tmp, dimNum ) ;
00191 sprintf(tmp+tlen,"\n") ;
00192 YY_BUFFER_STATE bstate = up_scan_string( tmp ) ;
00193
00194 bool parsed = !upparse() ;
00195
00196 up_delete_buffer( bstate ) ;
00197 delete [] tmp ;
00198
00199 if ( parsed && theResult ) {
00200 m_val = theResult->m_val ;
00201 m_dimn = theResult->m_dimn ;
00202 m_units = theResult->m_units ;
00203 m_dgrp = theResult->m_dgrp ;
00204 m_scale = theResult->m_scale ;
00205 } else {
00206 throw new runtime_error( "Could not parse units" ) ;
00207 }
00208 }
00209
00212 Quantity::Quantity( double v, UnitExpr* e )
00213 : m_val(v)
00214 {
00215 m_scale = 1.0 ;
00216 p_eval( e, 1, m_units, m_dimn, m_scale ) ;
00217 if ( m_units.size() == 0 )
00218 m_units.push_back( UnitPower( Unit::dimensionless(), 0, 1 ) ) ;
00219 if ( m_dimn.size() == 0 )
00220 m_dimn.push_back( DimensionPower( find_dsym('1'), 1 ) ) ;
00221 m_dgrp = DimensionGroup::find( m_dimn );
00222 }
00223
00226 Quantity::~Quantity()
00227 {
00228
00229 }
00230
00233 void Quantity::print()
00234 {
00235 fprintf( stdout, " %f [", m_val ) ;
00236 UnitPower::print( m_units, stdout ) ;
00237 fprintf( stdout, "] {" ) ;
00238
00239 fprintf( stdout, "}\n" ) ;
00240 }
00241
00249 bool Quantity::operator == ( const Quantity& o ) const
00250 {
00251 if ( m_val != o.m_val )
00252 return false ;
00253
00254 if ( m_dgrp && o.m_dgrp && m_dgrp == o.m_dgrp )
00255 return true ;
00256
00257 return ( m_dimn == o.m_dimn ) ;
00258 }
00259
00275 int convert( Quantity* to, const Quantity* from )
00276 {
00277 #ifdef DBG_CONVERT
00278 fprintf( stderr, "Convert [") ;
00279 UnitPower::print( from->m_units, stderr ) ;
00280 fprintf( stderr, "] {" ) ;
00281 DimensionPower::print( from->m_dimn, stderr ) ;
00282 fprintf( stderr, "} to [" ) ;
00283 UnitPower::print( to->m_units, stderr ) ;
00284 fprintf( stderr, "] {" ) ;
00285 DimensionPower::print( to->m_dimn, stderr ) ;
00286 fprintf( stderr, "}\n" ) ;
00287 #endif // DBG_CONVERT
00288
00289 if ( (from && to ) &&
00290 areDimensionsMatched(from->dimension(), to->dimension()) ) {
00291
00292 if ( from->m_units.size() == 1 &&
00293 to->m_units.size() == 1 &&
00294 (from->m_units[0].m_unit->offsetPolicy() ||
00295 to->m_units[0].m_unit->offsetPolicy()) ) {
00296
00297
00298 double o_from = from->m_units[0].m_unit->offsetValue() ;
00299 double o_to = to->m_units[0].m_unit->offsetValue() ;
00300 to->m_val = ( from->val() + o_from ) * from->scale()/to->scale() - o_to ;
00301 } else {
00302 to->m_val = from->val() * from->scale()/to->scale() ;
00303 }
00304 return 0 ;
00305 }
00306 to->m_val = dtNaN ;
00307 return 1 ;
00308 }
00309
00313 xmlNodePtr Quantity::mathML() const
00314 {
00315 CHAR* content ;
00316 xmlNodePtr top = xmlNewNode( NULL, (const CHAR*)"mrow" ) ;
00317
00318 content = (CHAR*) g_strdup_printf( "%g", m_val ) ;
00319 xmlNewChild( xmlNewChild( top, NULL, (const CHAR*)"mrow", NULL ),
00320 NULL, (const CHAR*)"mi", content ) ;
00321 g_free( content ) ;
00322
00323 xmlNewChild( top, NULL,
00324 (const CHAR*)"mo", (const CHAR*)" " ) ;
00325 xmlAddChild( top, UnitPower::mathML( m_units ) ) ;
00326
00327 return top ;
00328 }
00329