00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <math.h>
00025 #include <float.h>
00026
00027 #include <kdebug.h>
00028 #include <klocale.h>
00029
00030 #include <koscript_parser.h>
00031 #include <koscript_util.h>
00032 #include <koscript_func.h>
00033 #include <koscript_synext.h>
00034
00035 #include "kspread_cell.h"
00036 #include "kspread_sheet.h"
00037 #include "kspread_interpreter.h"
00038 #include "kspread_doc.h"
00039 #include "kspread_functions.h"
00040 #include "kspread_functions_helper.h"
00041 #include "kspread_util.h"
00042
00043 namespace math_local
00044 {
00045 KSpreadCell * gCell = 0;
00046 }
00047
00048 using namespace math_local;
00049
00050
00051 bool kspreadfunc_abs( KSContext& context );
00052 bool kspreadfunc_ceil( KSContext& context );
00053 bool kspreadfunc_ceiling( KSContext& context );
00054 bool kspreadfunc_count( KSContext& context );
00055 bool kspreadfunc_counta( KSContext& context );
00056 bool kspreadfunc_countblank( KSContext& context );
00057 bool kspreadfunc_countif( KSContext& context );
00058 bool kspreadfunc_cur( KSContext& context );
00059 bool kspreadfunc_div( KSContext& context );
00060 bool kspreadfunc_eps( KSContext& context );
00061 bool kspreadfunc_even( KSContext& context );
00062 bool kspreadfunc_exp( KSContext& context );
00063 bool kspreadfunc_fact( KSContext& context );
00064 bool kspreadfunc_factdouble( KSContext& context );
00065 bool kspreadfunc_fib( KSContext& context );
00066 bool kspreadfunc_floor( KSContext& context );
00067 bool kspreadfunc_gcd( KSContext & context );
00068 bool kspreadfunc_int( KSContext& context );
00069 bool kspreadfunc_inv( KSContext& context );
00070 bool kspreadfunc_kproduct( KSContext& context );
00071 bool kspreadfunc_lcm( KSContext & context );
00072 bool kspreadfunc_ln( KSContext& context );
00073 bool kspreadfunc_log( KSContext& context );
00074 bool kspreadfunc_log2( KSContext& context );
00075 bool kspreadfunc_log10( KSContext& context );
00076 bool kspreadfunc_logn( KSContext& context );
00077 bool kspreadfunc_max( KSContext& context );
00078 bool kspreadfunc_maxa( KSContext& context );
00079 bool kspreadfunc_min( KSContext& context );
00080 bool kspreadfunc_mina( KSContext& context );
00081 bool kspreadfunc_mod( KSContext& context );
00082 bool kspreadfunc_mround( KSContext& context );
00083 bool kspreadfunc_mult( KSContext& context );
00084 bool kspreadfunc_multinomial( KSContext& context );
00085 bool kspreadfunc_odd( KSContext& context );
00086 bool kspreadfunc_pow( KSContext& context );
00087 bool kspreadfunc_quotient( KSContext& context );
00088 bool kspreadfunc_product( KSContext& context );
00089 bool kspreadfunc_rand( KSContext& context );
00090 bool kspreadfunc_randbetween( KSContext& context );
00091 bool kspreadfunc_randbernoulli( KSContext & context );
00092 bool kspreadfunc_randbinom( KSContext & context );
00093 bool kspreadfunc_randexp( KSContext & context );
00094 bool kspreadfunc_randnegbinom( KSContext & context );
00095 bool kspreadfunc_randnorm( KSContext & context );
00096 bool kspreadfunc_randpoisson( KSContext & context );
00097 bool kspreadfunc_rootn( KSContext& context );
00098 bool kspreadfunc_round( KSContext& context );
00099 bool kspreadfunc_rounddown( KSContext& context );
00100 bool kspreadfunc_roundup( KSContext& context );
00101 bool kspreadfunc_sign( KSContext& context );
00102 bool kspreadfunc_sqrt( KSContext& context );
00103 bool kspreadfunc_sqrtpi( KSContext& context );
00104 bool kspreadfunc_subtotal( KSContext& context );
00105 bool kspreadfunc_sum( KSContext& context );
00106 bool kspreadfunc_sumif( KSContext& context );
00107 bool kspreadfunc_suma( KSContext& context );
00108 bool kspreadfunc_sumsq( KSContext& context );
00109 bool kspreadfunc_trunc( KSContext& context );
00110
00111
00112 bool kspreadfunc_multipleOP( KSContext& context );
00113
00114
00115 void KSpreadRegisterMathFunctions()
00116 {
00117 gCell = 0;
00118 KSpreadFunctionRepository * repo = KSpreadFunctionRepository::self();
00119
00120 repo->registerFunction( "MULTIPLEOPERATIONS", kspreadfunc_multipleOP );
00121
00122 repo->registerFunction( "ABS", kspreadfunc_abs );
00123 repo->registerFunction( "CEIL", kspreadfunc_ceil );
00124 repo->registerFunction( "CEILING", kspreadfunc_ceiling );
00125 repo->registerFunction( "COUNT", kspreadfunc_count );
00126 repo->registerFunction( "COUNTA", kspreadfunc_counta );
00127 repo->registerFunction( "COUNTBLANK", kspreadfunc_countblank );
00128 repo->registerFunction( "COUNTIF", kspreadfunc_countif );
00129 repo->registerFunction( "CUR", kspreadfunc_cur );
00130 repo->registerFunction( "DIV", kspreadfunc_div );
00131 repo->registerFunction( "EPS", kspreadfunc_eps );
00132 repo->registerFunction( "EVEN", kspreadfunc_even );
00133 repo->registerFunction( "EXP", kspreadfunc_exp );
00134 repo->registerFunction( "FACT", kspreadfunc_fact );
00135 repo->registerFunction( "FACTDOUBLE", kspreadfunc_factdouble );
00136 repo->registerFunction( "FIB", kspreadfunc_fib );
00137 repo->registerFunction( "FLOOR", kspreadfunc_floor );
00138 repo->registerFunction( "G_PRODUCT", kspreadfunc_kproduct );
00139 repo->registerFunction( "GCD", kspreadfunc_gcd );
00140 repo->registerFunction( "INT", kspreadfunc_int );
00141 repo->registerFunction( "INV", kspreadfunc_inv );
00142 repo->registerFunction( "KPRODUCT", kspreadfunc_kproduct );
00143 repo->registerFunction( "LCD", kspreadfunc_gcd );
00144 repo->registerFunction( "LCM", kspreadfunc_lcm );
00145 repo->registerFunction( "LN", kspreadfunc_ln );
00146 repo->registerFunction( "LOG", kspreadfunc_log );
00147 repo->registerFunction( "LOG2", kspreadfunc_log2 );
00148 repo->registerFunction( "LOG10", kspreadfunc_log10 );
00149 repo->registerFunction( "LOGN", kspreadfunc_logn );
00150 repo->registerFunction( "MAX", kspreadfunc_max );
00151 repo->registerFunction( "MAXA", kspreadfunc_maxa );
00152 repo->registerFunction( "MIN", kspreadfunc_min );
00153 repo->registerFunction( "MINA", kspreadfunc_mina );
00154 repo->registerFunction( "MOD", kspreadfunc_mod );
00155 repo->registerFunction( "MROUND", kspreadfunc_mround );
00156 repo->registerFunction( "MULTIPLY", kspreadfunc_mult );
00157 repo->registerFunction( "MULTINOMIAL", kspreadfunc_multinomial );
00158 repo->registerFunction( "ODD", kspreadfunc_odd );
00159 repo->registerFunction( "POW", kspreadfunc_pow );
00160 repo->registerFunction( "POWER", kspreadfunc_pow );
00161 repo->registerFunction( "QUOTIENT", kspreadfunc_quotient );
00162 repo->registerFunction( "PRODUCT", kspreadfunc_product );
00163 repo->registerFunction( "RAND", kspreadfunc_rand );
00164 repo->registerFunction( "RANDBERNOULLI", kspreadfunc_randbernoulli );
00165 repo->registerFunction( "RANDBETWEEN", kspreadfunc_randbetween );
00166 repo->registerFunction( "RANDBINOM", kspreadfunc_randbinom );
00167 repo->registerFunction( "RANDEXP", kspreadfunc_randexp );
00168 repo->registerFunction( "RANDNEGBINOM", kspreadfunc_randnegbinom );
00169 repo->registerFunction( "RANDNORM", kspreadfunc_randnorm );
00170 repo->registerFunction( "RANDPOISSON", kspreadfunc_randpoisson );
00171 repo->registerFunction( "ROOTN", kspreadfunc_rootn );
00172 repo->registerFunction( "ROUND", kspreadfunc_round );
00173 repo->registerFunction( "ROUNDDOWN", kspreadfunc_rounddown );
00174 repo->registerFunction( "ROUNDUP", kspreadfunc_roundup );
00175 repo->registerFunction( "SIGN", kspreadfunc_sign );
00176 repo->registerFunction( "SQRT", kspreadfunc_sqrt );
00177 repo->registerFunction( "SQRTPI", kspreadfunc_sqrtpi );
00178 repo->registerFunction( "SUBTOTAL", kspreadfunc_subtotal );
00179 repo->registerFunction( "SUM", kspreadfunc_sum );
00180 repo->registerFunction( "SUMIF", kspreadfunc_sumif );
00181 repo->registerFunction( "SUMA", kspreadfunc_suma );
00182 repo->registerFunction( "SUMSQ", kspreadfunc_sumsq );
00183 repo->registerFunction( "TRUNC", kspreadfunc_trunc );
00184 }
00185
00186
00187 bool kspreadfunc_sqrt( KSContext& context )
00188 {
00189 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00190
00191 if ( !KSUtil::checkArgumentsCount( context, 1, "sqrt", true ) )
00192 return false;
00193 double val=0.0;
00194 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00195 {
00196 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00197 return false;
00198 }
00199 else
00200 val=args[0]->doubleValue();
00201
00202 context.setValue( new KSValue( sqrt( val ) ) );
00203
00204 return true;
00205 }
00206
00207
00208 bool kspreadfunc_sqrtpi( KSContext& context )
00209 {
00210 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00211
00212 if ( !KSUtil::checkArgumentsCount( context, 1, "SQRTPI", true ) )
00213 return false;
00214 double val=0.0;
00215 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00216 {
00217 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00218 return false;
00219 }
00220 else
00221 val=args[0]->doubleValue();
00222
00223 if( val < 0 ) return false;
00224
00225 context.setValue( new KSValue( sqrt( val * M_PI ) ) );
00226 return true;
00227 }
00228
00229
00230
00231
00232
00233
00234 bool kspreadfunc_rootn( KSContext& context )
00235 {
00236 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00237
00238 if ( !KSUtil::checkArgumentsCount( context, 2, "SQRTn", true ) )
00239 return false;
00240
00241 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00242 return false;
00243 if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00244 return false;
00245
00246 context.setValue( new KSValue( exp( log(args[0]->doubleValue())/args[1]->intValue() ) ) );
00247
00248 return true;
00249 }
00250
00251
00252 bool kspreadfunc_cur( KSContext& context )
00253 {
00254 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00255
00256 if ( !KSUtil::checkArgumentsCount( context, 1, "CUR", true ) )
00257 return false;
00258
00259 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00260 return false;
00261
00262 context.setValue( new KSValue( exp( log(args[0]->doubleValue())/3)) );
00263
00264 return true;
00265 }
00266
00267
00268 bool kspreadfunc_abs( KSContext& context )
00269 {
00270 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00271
00272 if ( !KSUtil::checkArgumentsCount( context, 1, "ABS", true ) || !KSUtil::checkArgumentsCount( context, 1, "ABS", true ))
00273 return false;
00274
00275 double val=0.0;
00276 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00277 {
00278 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00279 return false;
00280 }
00281 else
00282 val=args[0]->doubleValue();
00283
00284 context.setValue( new KSValue( fabs(val ) ) );
00285
00286 return true;
00287 }
00288
00289
00290 bool kspreadfunc_exp( KSContext& context )
00291 {
00292 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00293
00294 if ( !KSUtil::checkArgumentsCount( context, 1, "exp",true ) )
00295 return false;
00296
00297 double val=0.0;
00298 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00299 {
00300 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00301 return false;
00302 }
00303 else
00304 val=args[0]->doubleValue();
00305
00306 context.setValue( new KSValue( exp( val ) ) );
00307
00308 return true;
00309 }
00310
00311
00312 bool kspreadfunc_ceil( KSContext& context )
00313 {
00314 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00315
00316 if ( !KSUtil::checkArgumentsCount( context, 1, "CEIL", true ) )
00317 return false;
00318
00319 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00320 return false;
00321 if ( approx_equal( floor( args[0]->doubleValue() ), args[0]->doubleValue() ) )
00322 context.setValue( new KSValue( args[0]->doubleValue() ) );
00323 else
00324 context.setValue( new KSValue( ceil( args[0]->doubleValue() ) ) );
00325
00326 return true;
00327 }
00328
00329
00330 bool kspreadfunc_ceiling( KSContext& context )
00331 {
00332 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00333
00334 double res;
00335 double number;
00336
00337 if ( !KSUtil::checkArgumentsCount( context, 2, "CEILING", true ) )
00338 {
00339 if ( !KSUtil::checkArgumentsCount( context, 1, "CEILING", true ) )
00340 return false;
00341
00342 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00343 return false;
00344
00345 number = args[0]->doubleValue();
00346
00347 if ( number >= 0 )
00348 res = 1.0;
00349 else
00350 res = -1.0;
00351 }
00352 else
00353 {
00354 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
00355 return false;
00356
00357 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00358 return false;
00359
00360 number = args[0]->doubleValue();
00361
00362 res = args[1]->doubleValue();
00363 }
00364
00365 if ( res == 0 )
00366 return false;
00367
00368 double d = number / res;
00369
00370 if ( d < 0 )
00371 return false;
00372
00373 if ( approx_equal( floor( d ), d ) )
00374 context.setValue( new KSValue( d * res ) );
00375 else
00376 context.setValue( new KSValue( ceil( d ) * res ) );
00377
00378 return true;
00379 }
00380
00381
00382 bool kspreadfunc_floor( KSContext& context )
00383 {
00384 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00385
00386 if ( !KSUtil::checkArgumentsCount( context, 1, "floor", true ) )
00387 return false;
00388
00389 double val=0.0;
00390 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00391 {
00392 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00393 return false;
00394 }
00395 else
00396 val=args[0]->doubleValue();
00397
00398 context.setValue( new KSValue( floor( val ) ) );
00399
00400 return true;
00401 }
00402
00403
00404 bool kspreadfunc_ln( KSContext& context )
00405 {
00406 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00407
00408 if ( !KSUtil::checkArgumentsCount( context, 1, "ln", true ) )
00409 return false;
00410
00411 double val=0.0;
00412 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00413 {
00414 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00415 return false;
00416 }
00417 else
00418 val=args[0]->doubleValue();
00419
00420 context.setValue( new KSValue( log( val ) ) );
00421
00422 return true;
00423 }
00424
00425
00426 bool kspreadfunc_logn( KSContext& context )
00427 {
00428 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00429
00430 if ( !KSUtil::checkArgumentsCount( context, 2, "LOGn", true ) )
00431 return false;
00432
00433 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00434 return false;
00435 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
00436 return false;
00437
00438 context.setValue( new KSValue( log( args[0]->doubleValue() ) /log( args[1]->doubleValue() )) );
00439
00440 return true;
00441 }
00442
00443
00444 bool kspreadfunc_log2( KSContext& context )
00445 {
00446 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00447
00448 if ( !KSUtil::checkArgumentsCount( context, 1, "LOG2", true ) )
00449 return false;
00450
00451 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00452 return false;
00453
00454 double d = args[0]->doubleValue();
00455
00456 if ( d <= 0 )
00457 return false;
00458
00459 context.setValue( new KSValue( log( d ) /log( 2.0 ) ) );
00460 return true;
00461 }
00462
00463
00464 bool kspreadfunc_log10( KSContext& context )
00465 {
00466 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00467
00468 if ( !KSUtil::checkArgumentsCount( context, 1, "LOG10", true ) )
00469 return false;
00470
00471 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00472 return false;
00473
00474 double d = args[0]->doubleValue();
00475
00476 if ( d <= 0 )
00477 return false;
00478
00479 context.setValue( new KSValue( log10( d ) ) );
00480 return true;
00481 }
00482
00483
00484 bool kspreadfunc_log( KSContext& context )
00485 {
00486 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00487
00488 if ( !KSUtil::checkArgumentsCount( context, 1, "log", true ) )
00489 return false;
00490
00491 double val=0.0;
00492 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00493 {
00494 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ))
00495 return false;
00496 }
00497 else
00498 val=args[0]->doubleValue();
00499
00500 context.setValue( new KSValue( log10( val ) ) );
00501
00502 return true;
00503 }
00504
00505 static bool kspreadfunc_sum_helper( KSContext & context, QValueList<KSValue::Ptr> & args,
00506 double & result, bool aMode )
00507 {
00508 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00509 QValueList<KSValue::Ptr>::Iterator end = args.end();
00510
00511 for( ; it != end; ++it )
00512 {
00513 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00514 {
00515 if ( !kspreadfunc_sum_helper( context, (*it)->listValue(), result, aMode ) )
00516 return false;
00517 }
00518 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00519 {
00520 result += (*it)->doubleValue();
00521 }
00522 else if ( aMode )
00523 {
00524 if ( KSUtil::checkType( context, *it, KSValue::StringType, false ) )
00525 {
00526
00527 }
00528 else
00529 if ( KSUtil::checkType( context, *it, KSValue::BoolType, false ) )
00530 {
00531 result += ( (*it)->boolValue() ? 1.0 : 0.0 );
00532 }
00533 }
00534 }
00535
00536 return true;
00537 }
00538
00539
00540 bool kspreadfunc_sum( KSContext & context )
00541 {
00542 double result = 0.0;
00543 bool b = kspreadfunc_sum_helper( context, context.value()->listValue(), result, false );
00544
00545 if ( b )
00546 context.setValue( new KSValue( result ) );
00547
00548 return b;
00549 }
00550
00551 static bool kspreadfunc_sumif_helper( KSContext & context, KSValue *value,
00552 QValueList<KSValue::Ptr> &args,
00553 KSpreadDB::Condition &cond,
00554 double & result, int &vpos, int &hpos )
00555 {
00556 if ( KSUtil::checkType( context, value, KSValue::DoubleType, false ) )
00557 {
00558 if ( conditionMatches( cond, value->doubleValue() ) ) {
00559 if( hpos == -1 )
00560 result += value->doubleValue();
00561 else {
00562 result += (args[2]->listValue()[vpos])-> listValue()[hpos]->doubleValue();
00563 ++hpos;
00564 }
00565 }
00566 return true;
00567 }
00568
00569 if ( KSUtil::checkType( context, value, KSValue::ListType, false ) ) {
00570 QValueList<KSValue::Ptr> values = value->listValue();
00571 QValueList<KSValue::Ptr>::Iterator it = values.begin();
00572 QValueList<KSValue::Ptr>::Iterator end = values.end();
00573
00574 for( ; it != end; ++it ) {
00575 if( !kspreadfunc_sumif_helper( context, *it, args, cond, result, vpos, hpos ) )
00576 return false;
00577 if ( vpos != -1 && KSUtil::checkType( context, *it, KSValue::ListType, false ) ){
00578 ++vpos;
00579 hpos = 0;
00580 }
00581 }
00582 return true;
00583 }
00584 return false;
00585 }
00586
00587 bool kspreadfunc_sumif( KSContext & context )
00588 {
00589 double result = 0.0;
00590 int hpos = -1; int vpos = -1;
00591 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00592
00593
00594 if( KSUtil::checkArgumentsCount( context, 3, "SUMIF", true ) ) {
00595
00596 QValueList<KSValue::Ptr> checkRange = args[0]->listValue();
00597 QValueList<KSValue::Ptr> sumRange = args[2]->listValue();
00598
00599 if( checkRange.count() <= sumRange.count() ) {
00600 for( uint i = 0 ; i < checkRange.count() ; ++i ) {
00601 if ( checkRange[i]->listValue().count() > sumRange[i]->listValue().count() )
00602 return false;
00603 }
00604
00605 hpos = 0;
00606 vpos = 0;
00607 } else return false;
00608
00609 } else if ( !KSUtil::checkArgumentsCount( context, 2, "SUMIF", false ) )
00610 return false;
00611
00612 if( !KSUtil::checkType( context, args[1], KSValue::StringType ) )
00613 return false;
00614
00615
00616 KSValue *value = args[0];
00617 KSpreadDB::Condition cond;
00618 getCond( cond, args[1]->stringValue() );
00619
00620 bool b = kspreadfunc_sumif_helper( context, value, args, cond, result, vpos, hpos );
00621
00622 if ( b ) {
00623 context.setValue( new KSValue( result ) );
00624 }
00625 return b;
00626 }
00627
00628
00629 bool kspreadfunc_suma( KSContext & context )
00630 {
00631 double result = 0.0;
00632 bool b = kspreadfunc_sum_helper( context, context.value()->listValue(), result, true );
00633
00634 if ( b )
00635 context.setValue( new KSValue( result ) );
00636
00637 return b;
00638 }
00639
00640 static bool kspreadfunc_product_helper( KSContext & context,
00641 QValueList<KSValue::Ptr> & args,
00642 double & result, int & number )
00643 {
00644 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00645 QValueList<KSValue::Ptr>::Iterator end = args.end();
00646
00647 for( ; it != end; ++it )
00648 {
00649 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00650 {
00651 if ( !kspreadfunc_product_helper( context, (*it)->listValue(), result, number ) )
00652 return false;
00653 }
00654 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00655 {
00656 ++number;
00657 result *= (*it)->doubleValue();
00658 }
00659 }
00660
00661 return true;
00662 }
00663
00664
00665 bool kspreadfunc_product( KSContext& context )
00666 {
00667 double result = 1.0;
00668 int number = 0;
00669 bool b = kspreadfunc_product_helper( context,
00670 context.value()->listValue(),
00671 result, number );
00672
00673 if ( number == 0 )
00674 result = 0.0;
00675
00676 if ( b )
00677 context.setValue( new KSValue( result ) );
00678
00679 return b;
00680 }
00681
00682
00683 bool kspreadfunc_kproduct( KSContext& context )
00684 {
00685 double result = 1.0;
00686 int number = 0;
00687 bool b = kspreadfunc_product_helper( context,
00688 context.value()->listValue(),
00689 result, number );
00690
00691 if ( b )
00692 context.setValue( new KSValue( result ) );
00693
00694 return b;
00695 }
00696
00697 static int kspreadfunc_div_helper( KSContext & context,
00698 QValueList<KSValue::Ptr> & args,
00699 double & result )
00700 {
00701 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00702 QValueList<KSValue::Ptr>::Iterator end = args.end();
00703
00704 result = (*it)->doubleValue();
00705 ++it;
00706 int number = 0;
00707
00708 for( ; it != end; ++it )
00709 {
00710 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00711 {
00712 if ( !kspreadfunc_product_helper( context, (*it)->listValue(), result, number ) )
00713 return 0;
00714 }
00715 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00716 {
00717 double val =(*it)->doubleValue();
00718
00719 if (val == 0)
00720 return -1;
00721
00722 result /= val;
00723 }
00724 }
00725
00726 return 1;
00727 }
00728
00729
00730 bool kspreadfunc_div( KSContext& context )
00731 {
00732 double result = 0.0;
00733 int b = kspreadfunc_div_helper( context,
00734 context.value()->listValue(),
00735 result );
00736
00737 if ( b == 1 )
00738 context.setValue( new KSValue( result ) );
00739 else if ( b == -1 )
00740 context.setValue( new KSValue( i18n("#DIV/0") ) );
00741 else
00742 return false;
00743
00744 return true;
00745 }
00746
00747 static bool kspreadfunc_sumsq_helper( KSContext& context, QValueList<KSValue::Ptr>& args, double& result )
00748 {
00749 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00750 QValueList<KSValue::Ptr>::Iterator end = args.end();
00751
00752 for( ; it != end; ++it )
00753 {
00754 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00755 {
00756 if ( !kspreadfunc_sum_helper( context, (*it)->listValue(), result, false ) )
00757 return false;
00758 }
00759 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00760 {
00761 result += ((*it)->doubleValue()*(*it)->doubleValue());
00762 }
00763 else if ( !KSUtil::checkType( context, *it, KSValue::Empty, true ) )
00764 return false;
00765 }
00766
00767 return true;
00768 }
00769
00770
00771 bool kspreadfunc_sumsq( KSContext& context )
00772 {
00773 double result = 0.0;
00774 bool b = kspreadfunc_sumsq_helper( context, context.value()->listValue(), result );
00775
00776 if ( b )
00777 context.setValue( new KSValue( result ) );
00778
00779 return b;
00780 }
00781
00782 static bool kspreadfunc_max_helper( KSContext & context, QValueList<KSValue::Ptr> & args,
00783 double & result, int & inter, int mode )
00784 {
00785 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00786 QValueList<KSValue::Ptr>::Iterator end = args.end();
00787
00788 for( ; it != end; ++it )
00789 {
00790 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00791 {
00792
00793 if ( !kspreadfunc_max_helper( context, (*it)->listValue(), result, inter, mode ) )
00794 return false;
00795 }
00796 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00797 {
00798 if ( inter == 0 )
00799 {
00800 result = (*it)->doubleValue();
00801 inter = 1;
00802 }
00803 if ( result < (*it)->doubleValue() )
00804 result = (*it)->doubleValue();
00805 }
00806 else if ( mode == 1 && KSUtil::checkType( context, *it, KSValue::BoolType, true ) )
00807 {
00808 double n = ( (*it)->boolValue() ? 1.0 : 0.0 );
00809 if ( inter == 0 )
00810 {
00811 result = n;
00812 inter = 1;
00813 }
00814 if ( result < n )
00815 result = n;
00816 }
00817 }
00818
00819 return true;
00820 }
00821
00822
00823 bool kspreadfunc_max( KSContext& context )
00824 {
00825 double result = 0.0;
00826
00827
00828 int inter=0;
00829
00830 bool b = kspreadfunc_max_helper( context, context.value()->listValue(), result, inter, 0 );
00831
00832 if ( b )
00833 context.setValue( new KSValue( result ) );
00834
00835 return b;
00836 }
00837
00838
00839 bool kspreadfunc_maxa( KSContext & context )
00840 {
00841 double result = 0.0;
00842
00843
00844 int inter = 0;
00845
00846 bool b = kspreadfunc_max_helper( context, context.value()->listValue(), result, inter, 1 );
00847
00848 if ( b )
00849 context.setValue( new KSValue( result ) );
00850
00851 return b;
00852 }
00853
00854 static int kspreadfunc_gcd_gcd(int value1, int value2)
00855 {
00856
00857 int n = (value1 <= value2 ? value1 : value2);
00858
00859
00860 if ((value1 % n == 0) && (value2 % n == 0))
00861 {
00862 return n;
00863 }
00864
00865 n = (int) (n / 2);
00866
00867 while ((value1 % n != 0) || (value2 % n != 0))
00868 {
00869 --n;
00870 }
00871
00872 return n;
00873 }
00874
00875 static bool kspreadfunc_gcd_helper( KSContext & context,
00876 QValueList<KSValue::Ptr>& args,
00877 int & result)
00878 {
00879 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00880 QValueList<KSValue::Ptr>::Iterator end = args.end();
00881
00882
00883 for( ; it != end; ++it )
00884 {
00885 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00886 {
00887 if ( !kspreadfunc_gcd_helper( context, (*it)->listValue(), result ) )
00888 return false;
00889 }
00890 else if ( KSUtil::checkType( context, *it, KSValue::IntType, true ) )
00891 {
00892 int val = (*it)->intValue();
00893
00894 if (val == 0)
00895 {
00896 result = 0;
00897 return true;
00898 }
00899
00900 if ((result == 0) || (val < result))
00901 result = val;
00902 }
00903 }
00904
00905 it = args.begin();
00906
00907
00908 for( ; it != end; ++it )
00909 {
00910 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00911 {
00912 if ( !kspreadfunc_gcd_helper( context, (*it)->listValue(), result ) )
00913 return false;
00914 }
00915 else if ( KSUtil::checkType( context, *it, KSValue::IntType, true ) )
00916 {
00917 int n = kspreadfunc_gcd_gcd(result, (*it)->intValue());
00918
00919 if (n != result)
00920 {
00921 result = n;
00922 it = args.begin();
00923
00924 continue;
00925 }
00926 }
00927 }
00928
00929 if (result < 0)
00930 result *= -1;
00931
00932 context.setValue(new KSValue(result));
00933
00934 return true;
00935 }
00936
00937
00938 bool kspreadfunc_gcd( KSContext & context )
00939 {
00940 int result = 0;
00941
00942 bool b = kspreadfunc_gcd_helper(context, context.value()->listValue(),
00943 result);
00944
00945 if (b)
00946 context.setValue(new KSValue(result));
00947
00948 return b;
00949 }
00950
00951 static bool kspreadfunc_lcm_helper( KSContext & context,
00952 QValueList<KSValue::Ptr> & args,
00953 double & result,
00954 double & max,
00955 double & inter,
00956 int & signs)
00957 {
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00969 QValueList<KSValue::Ptr>::Iterator end = args.end();
00970
00971
00972
00973 for (; it != end; ++it)
00974 {
00975 if (KSUtil::checkType(context, *it, KSValue::ListType, false))
00976 {
00977 if (!kspreadfunc_lcm_helper(context, (*it)->listValue(), result, max, inter, signs))
00978 return false;
00979 }
00980 else if (KSUtil::checkType(context, *it, KSValue::DoubleType, true))
00981 {
00982 double d = (double) (*it)->doubleValue();
00983
00984 if (d < 0)
00985 ++signs;
00986
00987 if (result < d)
00988 result = d;
00989 }
00990 }
00991
00992 inter = result;
00993 it = args.begin();
00994
00995 while (true)
00996 {
00997 if (KSUtil::checkType(context, *it, KSValue::ListType, false))
00998 {
00999 if (!kspreadfunc_lcm_helper( context, (*it)->listValue(), result, max, inter, signs))
01000 return false;
01001 }
01002 else if (KSUtil::checkType(context, *it, KSValue::DoubleType, true))
01003 {
01004 double d = inter / (*it)->doubleValue();
01005
01006
01007 if (!approx_equal(d, floor(d)))
01008 {
01009 inter += result;
01010
01011 it = args.begin();
01012 continue;
01013 }
01014 }
01015
01016
01017 ++it;
01018
01019 if (it == end)
01020 break;
01021 }
01022
01023 result = inter;
01024
01025
01026 if (signs > 0)
01027 {
01028 if ((result < 0) && (signs % 2 == 0))
01029 result *= -1;
01030 else if ((result > 0) && (signs % 2 != 0))
01031 result *= -1;
01032 }
01033
01034 return true;
01035 }
01036
01037
01038 bool kspreadfunc_lcm( KSContext & context )
01039 {
01040 double result = 0.0;
01041 double max = 1.0;
01042 double inter = 0.0;
01043 int signs = 0;
01044
01045 bool b = kspreadfunc_lcm_helper(context, context.value()->listValue(),
01046 result, max, inter, signs);
01047
01048 if (b)
01049 context.setValue(new KSValue(result));
01050
01051 return b;
01052
01053 }
01054
01055 static bool kspreadfunc_min_helper( KSContext & context, QValueList<KSValue::Ptr> & args,
01056 double & result, int & inter, int mode )
01057 {
01058 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01059 QValueList<KSValue::Ptr>::Iterator end = args.end();
01060
01061 for ( ; it != end; ++it )
01062 {
01063 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
01064 {
01065
01066 if ( !kspreadfunc_min_helper( context, (*it)->listValue(), result, inter, mode ) )
01067 return false;
01068 }
01069 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
01070 {
01071 if ( inter == 0 )
01072 {
01073 result = (*it)->doubleValue();
01074 inter = 1;
01075 }
01076 if ( result > (*it)->doubleValue() )
01077 result = (*it)->doubleValue();
01078 }
01079 else if ( mode == 1 && KSUtil::checkType( context, *it, KSValue::BoolType, true ) )
01080 {
01081 double n = ( (*it)->boolValue() ? 1.0 : 0.0 );
01082 if ( inter == 0 )
01083 {
01084 result = n;
01085 inter = 1;
01086 }
01087 if ( result > n )
01088 result = n;
01089 }
01090 }
01091
01092 return true;
01093 }
01094
01095
01096 bool kspreadfunc_min( KSContext& context )
01097 {
01098 double result = 0.0;
01099
01100
01101 int inter = 0;
01102
01103 bool b = kspreadfunc_min_helper( context, context.value()->listValue(), result, inter, 0 );
01104
01105 if ( b )
01106 context.setValue( new KSValue( result ) );
01107
01108 return b;
01109 }
01110
01111
01112 bool kspreadfunc_mina( KSContext& context )
01113 {
01114 double result = 0.0;
01115
01116
01117 int inter = 0;
01118
01119 bool b = kspreadfunc_min_helper( context, context.value()->listValue(), result, inter, 1 );
01120
01121 if ( b )
01122 context.setValue( new KSValue( result ) );
01123
01124 return b;
01125 }
01126
01127 static bool kspreadfunc_mult_helper( KSContext& context, QValueList<KSValue::Ptr>& args, double& result )
01128 {
01129 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01130 QValueList<KSValue::Ptr>::Iterator end = args.end();
01131
01132 for( ; it != end; ++it )
01133 {
01134 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
01135 {
01136 if ( !kspreadfunc_mult_helper( context, (*it)->listValue(), result ) )
01137 return false;
01138 }
01139 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
01140 result *= (*it)->doubleValue();
01141 }
01142
01143 return true;
01144 }
01145
01146
01147 bool kspreadfunc_mult( KSContext& context )
01148 {
01149 double result = 1.0;
01150 bool b = kspreadfunc_mult_helper( context, context.value()->listValue(), result );
01151
01152 if ( b )
01153 context.setValue( new KSValue( result ) );
01154
01155 return b;
01156 }
01157
01158
01159 bool kspreadfunc_int( KSContext& context )
01160 {
01161 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01162
01163 if ( !KSUtil::checkArgumentsCount( context, 1, "INT", true ) )
01164 return false;
01165 double val=0.0;
01166 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01167 {
01168 if(!KSUtil::checkType( context, args[0], KSValue::Empty, true ) )
01169 return false;
01170 }
01171 else
01172 val=args[0]->doubleValue();
01173
01174 context.setValue( new KSValue( floor( val ) ) );
01175 return true;
01176 }
01177
01178
01179 bool kspreadfunc_quotient( KSContext& context )
01180 {
01181 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01182
01183 if ( !KSUtil::checkArgumentsCount( context, 2, "QUOTIENT", true ) )
01184 return false;
01185
01186 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01187 return false;
01188
01189 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
01190 return false;
01191
01192 double num = args[0]->doubleValue();
01193 double den = args[1]->doubleValue();
01194
01195 if( den == 0 ) return false;
01196
01197 context.setValue( new KSValue( (int)(num/den) ) );
01198 return true;
01199 }
01200
01201
01202
01203 bool kspreadfunc_eps( KSContext& context )
01204 {
01205
01206 if( !KSUtil::checkArgumentsCount( context, 0, "eps", true ) )
01207 return false;
01208
01209 context.setValue( new KSValue(DBL_EPSILON));
01210 return true;
01211 }
01212
01213 bool kspreadfunc_randexp( KSContext & context )
01214 {
01215 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01216
01217 if ( !KSUtil::checkArgumentsCount( context, 1, "RANDEXP", true ) )
01218 return false;
01219
01220 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01221 return false;
01222
01223 double d = args[0]->doubleValue();
01224
01225 d = -1 * d * log( (double) rand() / ( RAND_MAX + 1.0 ) );
01226
01227 context.setValue( new KSValue( d ) );
01228 return true;
01229 }
01230
01231 bool kspreadfunc_randbinom( KSContext & context )
01232 {
01233 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01234
01235 if ( !KSUtil::checkArgumentsCount( context, 2, "RANDBINOM", true ) )
01236 return false;
01237
01238 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01239 return false;
01240 if( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01241 return false;
01242
01243 double d = args[0]->doubleValue();
01244 int tr = args[1]->intValue();
01245
01246 if ( d < 0 || d > 1 )
01247 return false;
01248
01249 if ( tr < 0 )
01250 return false;
01251
01252
01253 double x = pow(1 - d, tr);
01254 double r = (double) rand() / ( RAND_MAX + 1.0 );
01255 double t = x;
01256 double i = 0;
01257
01258 while (r > t)
01259 {
01260 x *= (((tr - i) * d) / ((1 + i) * (1 - d)));
01261 i += 1;
01262 t += x;
01263 }
01264
01265 context.setValue( new KSValue( i ) );
01266 return true;
01267 }
01268
01269 bool kspreadfunc_randnegbinom( KSContext & context )
01270 {
01271 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01272
01273 if ( !KSUtil::checkArgumentsCount( context, 2, "RANDNEGBINOM", true ) )
01274 return false;
01275
01276 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01277 return false;
01278 if( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01279 return false;
01280
01281 double d = args[0]->doubleValue();
01282 int f = args[1]->intValue();
01283
01284 if ( d < 0 || d > 1 )
01285 return false;
01286
01287 if ( f < 0 )
01288 return false;
01289
01290
01291 double x = pow(d, f);
01292 double r = (double) rand() / ( RAND_MAX + 1.0 );
01293 double t = x;
01294 double i = 0;
01295
01296 while (r > t)
01297 {
01298 x *= ( ( ( f + i ) * ( 1 - d ) ) / (1 + i) ) ;
01299 i += 1;
01300 t += x;
01301 }
01302
01303 context.setValue( new KSValue( i ) );
01304 return true;
01305 }
01306
01307 bool kspreadfunc_randbernoulli( KSContext & context )
01308 {
01309 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01310
01311 if ( !KSUtil::checkArgumentsCount( context, 1, "RANDBERNOULLI", true ) )
01312 return false;
01313
01314 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01315 return false;
01316
01317 double d = args[0]->doubleValue();
01318 if ( d < 0 || d > 1 )
01319 return false;
01320
01321
01322 double r = (double) rand() / ( RAND_MAX + 1.0 );
01323
01324 context.setValue( new KSValue( ( r <= d ) ? 1.0 : 0.0 ) );
01325 return true;
01326 }
01327
01328 bool kspreadfunc_randnorm( KSContext & context )
01329 {
01330 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01331
01332 if ( !KSUtil::checkArgumentsCount( context, 2, "RANDNORM", true ) )
01333 return false;
01334
01335 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01336 return false;
01337 if( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
01338 return false;
01339
01340 double mu = args[0]->doubleValue();
01341 double sigma = args[1]->doubleValue();
01342
01343
01344
01345
01346 double x1, x2, w;
01347 do {
01348 x1 = (double) rand() / (RAND_MAX + 1.0);
01349 x2 = (double) rand() / (RAND_MAX + 1.0);
01350 x1 = 2.0 * x1 - 1.0;
01351 x2 = 2.0 * x2 - 1.0;
01352 w = x1 * x1 + x2 * x2;
01353 } while (w >= 1.0);
01354
01355 w = sqrt ((-2.0 * log (w)) / w);
01356 double res = x1 * w;
01357
01358 res = res * sigma + mu;
01359 context.setValue( new KSValue( res ) );
01360 return true;
01361 }
01362
01363 bool kspreadfunc_randpoisson( KSContext & context )
01364 {
01365 QValueList<KSValue::Ptr> & args = context.value()->listValue();
01366
01367 if ( !KSUtil::checkArgumentsCount( context, 1, "RANDPOISSON", true ) )
01368 return false;
01369
01370 if( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01371 return false;
01372
01373 double d = args[0]->doubleValue();
01374 if ( d < 0 )
01375 return false;
01376
01377
01378 double x = exp( -1 * d );
01379 double r = ( double ) rand() / ( RAND_MAX + 1.0 );
01380 double t = x;
01381 double i = 0;
01382
01383 while ( r > t )
01384 {
01385 x *= d / ( i + 1 );
01386 i += 1;
01387 t += x;
01388 }
01389
01390 context.setValue( new KSValue( i ) );
01391 return true;
01392 }
01393
01394
01395 bool kspreadfunc_rand( KSContext& context )
01396 {
01397
01398
01399 if ( !KSUtil::checkArgumentsCount( context, 0, "rand", true ) )
01400 return false;
01401
01402 context.setValue( new KSValue((double) rand()/(RAND_MAX + 1.0)));
01403 return true;
01404 }
01405
01406
01407 bool kspreadfunc_randbetween( KSContext& context )
01408 {
01409 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01410
01411 if ( !KSUtil::checkArgumentsCount( context, 2, "RANDBETWEEN", true ) )
01412 return false;
01413 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01414 return false;
01415 if( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01416 return false;
01417 if(args[0]->intValue()>args[1]->intValue())
01418 {
01419 context.setValue( new KSValue(i18n("Err")));
01420 return true;
01421 }
01422
01423 context.setValue( new KSValue((double)(((double)args[1]->intValue()-(double)args[0]->intValue())*rand()/RAND_MAX+((double)args[0]->intValue()))));
01424
01425 return true;
01426 }
01427
01428
01429 bool kspreadfunc_pow( KSContext& context )
01430 {
01431 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01432
01433 if ( !KSUtil::checkArgumentsCount( context, 2, "pow",true ) )
01434 return false;
01435
01436 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01437 return false;
01438
01439 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
01440 return false;
01441
01442 context.setValue( new KSValue( pow( args[0]->doubleValue(),args[1]->doubleValue() ) ) );
01443
01444 return true;
01445 }
01446
01447
01448 bool kspreadfunc_mod( KSContext& context )
01449 {
01450 double result=0;
01451 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01452
01453 if ( !KSUtil::checkArgumentsCount( context, 2, "MOD",true ) )
01454 return false;
01455
01456 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01457 return false;
01458
01459 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
01460 return false;
01461 if( (int)args[1]->doubleValue()!=0)
01462 {
01463 result=(int)args[0]->doubleValue() % (int)args[1]->doubleValue();
01464 if( result < 0 ) result += (int)args[1]->doubleValue();
01465 context.setValue( new KSValue( result ) );
01466 }
01467 else
01468 {
01469 context.setValue( new KSValue( i18n("#DIV/0") ) );
01470
01471 }
01472 return true;
01473 }
01474
01475
01476 bool kspreadfunc_fact( KSContext& context )
01477 {
01478 double result;
01479 QString tmp;
01480 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01481
01482 if ( !KSUtil::checkArgumentsCount( context,1, "fact",true ) )
01483 return false;
01484
01485 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01486 return false;
01487
01488 result=util_fact((double)args[0]->intValue(),0);
01489
01490 tmp=i18n("Err");
01491 if(result==-1)
01492 context.setValue( new KSValue(tmp));
01493 else
01494 context.setValue( new KSValue(result ));
01495
01496 return true;
01497 }
01498
01499
01500 bool kspreadfunc_factdouble( KSContext& context )
01501 {
01502 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01503
01504 if ( !KSUtil::checkArgumentsCount( context, 1, "FACTDOUBLE",true ) )
01505 return false;
01506
01507 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01508 return false;
01509
01510 int number = args[0]->intValue();
01511 if( number < 0 )
01512 return false;
01513
01514 double result = 1;
01515 for( int n = number; n > 0; n -= 2 )
01516 result *= n;
01517
01518 context.setValue( new KSValue( result ) );
01519
01520 return true;
01521 }
01522
01523
01524 bool kspreadfunc_multinomial( KSContext& context )
01525 {
01526 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01527
01528 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01529 QValueList<KSValue::Ptr>::Iterator end = args.end();
01530
01531 double num = 0, den = 1;
01532
01533 for( ; it != end; ++it )
01534 {
01535 if ( KSUtil::checkType( context, *it, KSValue::IntType, false ) )
01536 {
01537 int val = (*it)->intValue();
01538 if( val < 0 ) return false;
01539 num += val;
01540 den *= util_fact( val, 0 );
01541 }
01542 }
01543
01544 num = util_fact( num, 0 );
01545 double result = num / den;
01546
01547 context.setValue( new KSValue( result ) );
01548 return true;
01549 }
01550
01551
01552 bool kspreadfunc_sign( KSContext& context )
01553 {
01554 int value=0;
01555 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01556
01557 if ( !KSUtil::checkArgumentsCount( context, 1, "sign", true ) )
01558 return false;
01559 double val=0.0;
01560 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01561 {
01562 if ( !KSUtil::checkType( context, args[0], KSValue::Empty, true ) )
01563 return false;
01564 }
01565 val=args[0]->doubleValue();
01566
01567 if(val>0)
01568 value=1;
01569 else if(val<0)
01570 value=-1;
01571 else if(val==0)
01572 value=0;
01573
01574 context.setValue( new KSValue( value ) );
01575
01576 return true;
01577 }
01578
01579
01580 bool kspreadfunc_inv( KSContext& context )
01581 {
01582 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01583
01584 if ( !KSUtil::checkArgumentsCount( context, 1, "INV",true ) )
01585 return false;
01586 double val=0.0;
01587 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01588 {
01589 if ( !KSUtil::checkType( context, args[0], KSValue::Empty, true ) )
01590 return false;
01591 }
01592 val=args[0]->doubleValue();
01593
01594
01595 context.setValue( new KSValue( val*(-1) ) );
01596
01597 return true;
01598 }
01599
01600 bool kspreadfunc_mround( KSContext& context )
01601 {
01602 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01603
01604 if ( !KSUtil::checkArgumentsCount( context, 2, "MROUND", true ) )
01605 return false;
01606
01607 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01608 return false;
01609 if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
01610 return false;
01611
01612 double d = args[0]->doubleValue();
01613 double m = args[1]->doubleValue();
01614
01615 if ( ( d > 0 && m < 0 )
01616 || ( d < 0 && m > 0 ) )
01617 return false;
01618
01619 int sign = 1;
01620
01621 if ( d < 0 )
01622 {
01623 sign = -1;
01624 d = -d;
01625 m = -m;
01626 }
01627
01628
01629 double mod = fmod( d, m );
01630 double div = d - mod;
01631
01632 double accuracyLimit = 0.0000003;
01633 double result = sign * ( div + ( ( mod + accuracyLimit >= m / 2 ) ? m : 0 ) );
01634
01635 context.setValue( new KSValue( result ) );
01636 return true;
01637 }
01638
01639
01640 bool kspreadfunc_rounddown( KSContext& context )
01641 {
01642 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01643 double result=0;
01644 int digits=0;
01645 if ( !KSUtil::checkArgumentsCount( context, 2, "ROUNDDOWN", true ) )
01646 {
01647
01648 if ( !KSUtil::checkArgumentsCount( context, 1, "ROUNDDOWN", true ) )
01649 return false;
01650 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01651 return false;
01652 digits=0;
01653 }
01654 else
01655 {
01656 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01657 return false;
01658 if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01659 return false;
01660 digits=args[1]->intValue();
01661 }
01662 result=args[0]->doubleValue()*pow(10.0, digits);
01663 context.setValue( new KSValue( floor( result )/pow(10.0, digits) ) );
01664
01665 return true;
01666 }
01667
01668
01669 bool kspreadfunc_roundup( KSContext& context )
01670 {
01671 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01672 double result=0;
01673 int digits=0;
01674 if ( !KSUtil::checkArgumentsCount( context, 2, "ROUNDUP", true ) )
01675 {
01676
01677 if ( !KSUtil::checkArgumentsCount( context, 1, "ROUNDUP", true ) )
01678 return false;
01679 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01680 return false;
01681 digits=0;
01682 }
01683 else
01684 {
01685 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01686 return false;
01687 if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01688 return false;
01689 digits=args[1]->intValue();
01690 }
01691
01692
01693 if (approx_equal(floor(args[0]->doubleValue()*::pow(10,digits)), args[0]->doubleValue()*::pow(10,digits)))
01694 result = args[0]->doubleValue();
01695 else
01696 result=floor(args[0]->doubleValue()*::pow(10,digits)+1)/::pow(10,digits);
01697 context.setValue( new KSValue( result) );
01698
01699 return true;
01700 }
01701
01702
01703 bool kspreadfunc_round( KSContext& context )
01704 {
01705 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01706 double result=0;
01707 int digits=0;
01708 if ( !KSUtil::checkArgumentsCount( context, 2, "ROUND", true ) )
01709 {
01710
01711 if ( !KSUtil::checkArgumentsCount( context, 1, "ROUND", true ) )
01712 return false;
01713 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01714 return false;
01715 digits=0;
01716 }
01717 else
01718 {
01719 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01720 return false;
01721 if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01722 return false;
01723 digits=args[1]->intValue();
01724 }
01725 result=floor(args[0]->doubleValue()*pow(10.0,digits)+0.5)/pow(10.0,digits);
01726 context.setValue( new KSValue( result) );
01727
01728 return true;
01729 }
01730
01731
01732 bool kspreadfunc_even( KSContext& context )
01733 {
01734 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01735 if ( !KSUtil::checkArgumentsCount( context,1, "EVEN",true ) )
01736 return false;
01737
01738 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01739 return false;
01740 double result;
01741 double val=args[0]->doubleValue();
01742 int sign=1;
01743 if(val<0)
01744 {
01745 sign=-1;
01746 val=-val;
01747 }
01748 if (approx_equal(val, floor(val)))
01749 val = floor(val);
01750 double valsup=ceil( val );
01751 if(fmod(valsup,2.0)==0)
01752 {
01753 if(val>valsup)
01754 result=(int)(sign*(valsup+2));
01755 else
01756 result=(int)(sign*valsup);
01757 }
01758 else
01759 {
01760 result=(int)(sign*(valsup+1));
01761 }
01762 context.setValue( new KSValue(result));
01763
01764 return true;
01765 }
01766
01767
01768 bool kspreadfunc_odd( KSContext& context )
01769 {
01770 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01771 if ( !KSUtil::checkArgumentsCount( context,1, "ODD",true ) )
01772 return false;
01773
01774 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01775 return false;
01776 double result;
01777 double valsup;
01778 int sign=1;
01779 double val= args[0]->doubleValue();
01780 if (val < 0)
01781 {
01782 sign = -1;
01783 val = -val;
01784 }
01785 if (approx_equal(val, floor(val)))
01786 val = floor(val);
01787 valsup = ceil(val);
01788 if (fmod(valsup, 2.0) == 1)
01789 {
01790 if (val > valsup)
01791 result=(int) (sign * (valsup + 2));
01792 else
01793 result=(int) (sign * valsup);
01794 }
01795 else
01796 result=(int) (sign * (valsup + 1));
01797
01798 context.setValue( new KSValue(result));
01799
01800 return true;
01801 }
01802
01803 static bool kspreadfunc_count_helper( KSContext& context, QValueList<KSValue::Ptr> & args, double & result )
01804 {
01805 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01806 QValueList<KSValue::Ptr>::Iterator end = args.end();
01807
01808 for( ; it != end; ++it )
01809 {
01810 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
01811 {
01812 if ( !kspreadfunc_count_helper( context, (*it)->listValue(), result ) )
01813 return false;
01814 }
01815 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
01816 {
01817 ++result;
01818 }
01819 }
01820
01821 return true;
01822 }
01823
01824 bool kspreadfunc_trunc( KSContext & context )
01825 {
01826 QValueList<KSValue::Ptr>& args = context.value()->listValue();
01827 int precision = 0;
01828
01829 if( KSUtil::checkArgumentsCount( context, 2, "TRUNC", false ) )
01830 {
01831 if( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01832 return false;
01833
01834 precision = args[1]->intValue();
01835 }
01836 else
01837 {
01838 if ( !KSUtil::checkArgumentsCount( context, 1, "TRUNC", true ) )
01839 return false;
01840 }
01841
01842 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
01843 return false;
01844
01845 double result = args[0]->doubleValue();
01846
01847
01848 if( precision < 0 )
01849 {
01850 precision = -precision;
01851 result = floor( result/pow(10.0,precision) ) * pow(10.0,precision);
01852 precision = 0;
01853 }
01854
01855 int factor = (int) pow( 10.0, precision );
01856
01857 result = floor( result * factor ) / factor;
01858
01859 context.setValue( new KSValue( result ) );
01860
01861 return true;
01862 }
01863
01864
01865 bool kspreadfunc_count( KSContext& context )
01866 {
01867 double result = 0.0;
01868
01869 bool b = kspreadfunc_count_helper( context, context.value()->listValue(), result );
01870
01871 if ( b )
01872 context.setValue( new KSValue( result ) );
01873
01874 return b;
01875 }
01876
01877 static bool kspreadfunc_counta_helper( KSContext& context, QValueList<KSValue::Ptr> & args,
01878 QValueList<KSValue::Ptr> & extra, int & resultA )
01879 {
01880 QValueList<KSValue::Ptr>::Iterator eit = extra.begin();
01881 QValueList<KSValue::Ptr>::Iterator eend = extra.end();
01882
01883 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01884
01885 KSpreadMap * map = ((KSpreadInterpreter *) context.interpreter() )->document()->map();
01886 KSpreadSheet * sheet = ((KSpreadInterpreter *) context.interpreter() )->sheet();
01887 KSpreadSheet * t = 0;
01888 KSpreadCell * cell = 0;
01889
01890 for ( ; eit != eend; ++eit )
01891 {
01892 int right = 0;
01893 int left = 0;
01894 int bottom = 0;
01895 int top = 0;
01896 if ( KSUtil::checkType( context, *eit, KSValue::StringType, true ) )
01897 {
01898 KSpreadRange range( (*eit)->stringValue(), map );
01899 if ( range.range.left() <= 0 || range.range.right() <= 0 )
01900 {
01901 KSpreadPoint point( (*eit)->stringValue(), map );
01902 if ( point.pos.x() <= 0 || point.pos.y() <= 0 )
01903 return false;
01904
01905 right = point.pos.x();
01906 bottom = point.pos.y();
01907 left = right;
01908 top = bottom;
01909
01910 if ( !point.isSheetKnown() )
01911 t = sheet;
01912 else
01913 t = point.sheet;
01914 }
01915 else
01916 {
01917 right = range.range.right();
01918 bottom = range.range.bottom();
01919 left = range.range.left();
01920 top = range.range.top();
01921
01922 if ( !range.isSheetKnown() )
01923 t = sheet;
01924 else
01925 t = range.sheet;
01926 }
01927
01928 for ( int x = left; x <= right; ++x )
01929 {
01930 for ( int y = top; y <= bottom; ++y )
01931 {
01932 kdDebug() << "Cell: " << x << ", " << y << endl;
01933 cell = t->cellAt( x, y );
01934 if ( !cell->isDefault() && !cell->isEmpty() )
01935 {
01936 if ( !cell->strOutText().isEmpty() )
01937 ++resultA;
01938 }
01939 }
01940 }
01941 }
01942 else if ( KSUtil::checkType( context, *it, KSValue::StringType, true ) )
01943 {
01944 kdDebug() << "String value" << endl;
01945 if ( !(*it)->stringValue().isEmpty() )
01946 ++resultA;
01947 }
01948 else if ( !KSUtil::checkType( context, *it, KSValue::Empty, true ) )
01949 {
01950 kdDebug() << "Empty" << endl;
01951 ++resultA;
01952 }
01953
01954 ++it;
01955 }
01956
01957 return true;
01958 }
01959
01960
01961 bool kspreadfunc_counta( KSContext& context )
01962 {
01963 int resultA = 0;
01964
01965 bool b = kspreadfunc_counta_helper( context, context.value()->listValue(),
01966 context.extraData()->listValue(), resultA );
01967
01968 if ( b )
01969 context.setValue( new KSValue( resultA ) );
01970
01971 return b;
01972 }
01973
01974 static bool kspreadfunc_countblank_helper( KSContext& context, QValueList<KSValue::Ptr> & args,
01975 int & result )
01976 {
01977 KSpreadMap * map = ((KSpreadInterpreter *) context.interpreter() )->document()->map();
01978 KSpreadSheet * sheet = ((KSpreadInterpreter *) context.interpreter() )->sheet();
01979 KSpreadCell * cell = 0;
01980 KSpreadSheet * t = 0;
01981
01982 QValueList<KSValue::Ptr>::Iterator it = args.begin();
01983 QValueList<KSValue::Ptr>::Iterator end = args.end();
01984
01985 kdDebug() << "Result: " << result << endl;
01986
01987 for( ; it != end; ++it )
01988 {
01989 if ( KSUtil::checkType( context, *it, KSValue::StringType, false ) )
01990 {
01991 kdDebug() << "S:" << (*it)->stringValue() << endl;
01992 int right = 0;
01993 int left = 0;
01994 int bottom = 0;
01995 int top = 0;
01996
01997 KSpreadRange range( (*it)->stringValue(), map );
01998 if ( range.range.left() <= 0 || range.range.right() <= 0 )
01999 {
02000 KSpreadPoint point( (*it)->stringValue(), map );
02001
02002 if ( point.pos.x() <= 0 || point.pos.y() <= 0 )
02003 continue;
02004
02005 right = point.pos.x();
02006 bottom = point.pos.y();
02007 left = right;
02008 top = bottom;
02009
02010 if ( !point.isSheetKnown() )
02011 t = sheet;
02012 else
02013 t = point.sheet;
02014 }
02015 else
02016 {
02017 right = range.range.right();
02018 bottom = range.range.bottom();
02019 left = range.range.left();
02020 top = range.range.top();
02021
02022 if ( !range.isSheetKnown() )
02023 t = sheet;
02024 else
02025 t = range.sheet;
02026 }
02027
02028 for ( int x = left; x <= right; ++x )
02029 {
02030 for ( int y = top; y <= bottom; ++y )
02031 {
02032 kdDebug() << "Cell: " << x << ", " << y << endl;
02033 cell = t->cellAt( x, y );
02034 if ( cell->isDefault() || cell->isEmpty() || cell->strOutText().isEmpty() )
02035 {
02036 ++result;
02037 }
02038 }
02039 }
02040 }
02041 }
02042
02043 kdDebug() << "Result 2: " << result << endl;
02044
02045 return true;
02046 }
02047
02048
02049 bool kspreadfunc_countblank( KSContext& context )
02050 {
02051 int result = 0;
02052
02053 kdDebug() << "Countblank: " << endl;
02054
02055 bool b = kspreadfunc_countblank_helper( context, context.extraData()->listValue(), result );
02056
02057 if ( b )
02058 context.setValue( new KSValue( result ) );
02059
02060 return b;
02061 }
02062
02063 static int kspreadfunc_countif_helper( KSContext& context, KSValue *value,
02064 const QString &criteria )
02065 {
02066 if( KSUtil::checkType( context, value, KSValue::DoubleType, false ) )
02067 {
02068 KSpreadDB::Condition cond;
02069 getCond( cond, criteria );
02070
02071 return conditionMatches( cond, value->doubleValue() ) ? 1 : 0;
02072 }
02073
02074 if( KSUtil::checkType( context, value, KSValue::StringType, false ) )
02075 {
02076 KSpreadDB::Condition cond;
02077 getCond( cond, criteria );
02078
02079 return conditionMatches( cond, value->stringValue() ) ? 1 : 0;
02080 }
02081
02082 if( KSUtil::checkType( context, value, KSValue::BoolType, false ) )
02083 {
02084 bool criteria_bool = criteria.lower() == "true";
02085 if( !value && (criteria.lower() != "false") ) return 0;
02086 return criteria_bool == value->boolValue() ? 1 : 0;
02087 }
02088
02089 if( KSUtil::checkType( context, value, KSValue::ListType, false ) )
02090 {
02091 QValueList<KSValue::Ptr>& args = value->listValue();
02092 QValueList<KSValue::Ptr>::Iterator it = args.begin();
02093 QValueList<KSValue::Ptr>::Iterator end = args.end();
02094
02095 int count = 0;
02096 for( ; it != end; ++it )
02097 if ( !kspreadfunc_countif_helper( context, *it, criteria ) ) count++;
02098
02099 return count;
02100 }
02101
02102 return 0;
02103 }
02104
02105
02106 bool kspreadfunc_countif( KSContext& context )
02107 {
02108 QValueList<KSValue::Ptr>& args = context.value()->listValue();
02109
02110 if ( !KSUtil::checkArgumentsCount( context, 2, "COUNTIF", true ) )
02111 return false;
02112
02113 if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
02114 return false;
02115
02116 KSValue* value = args[0];
02117 QString criteria = args[1]->stringValue();
02118
02119 int result = kspreadfunc_countif_helper( context, value, criteria );
02120
02121 context.setValue( new KSValue( result ) );
02122 return true;
02123 }
02124
02125
02126 bool kspreadfunc_fib( KSContext& context )
02127 {
02128 QValueList<KSValue::Ptr>& args = context.value()->listValue();
02129 if ( !KSUtil::checkArgumentsCount( context, 1, "FIB", true ) )
02130 return false;
02131
02132 if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
02133 return false;
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143 double n = args[0]->doubleValue();
02144
02145 double s = sqrt(5.0);
02146 double result = ( pow((1+s)/2,n) - pow((1-s)/2,n) ) / s;
02147
02148 context.setValue( new KSValue( result ) );
02149 return true;
02150 }
02151
02152
02153 bool kspreadfunc_multipleOP( KSContext& context )
02154 {
02155 if (gCell)
02156 {
02157 context.setValue( new KSValue( ((KSpreadInterpreter *) context.interpreter() )->cell()->value().asFloat() ) );
02158 return true;
02159 }
02160
02161 gCell = ((KSpreadInterpreter *) context.interpreter() )->cell();
02162
02163 QValueList<KSValue::Ptr>& args = context.value()->listValue();
02164 QValueList<KSValue::Ptr>& extra = context.extraData()->listValue();
02165
02166 if ( !KSUtil::checkArgumentsCount( context, 5, "MULTIPLEOPERATIONS", true ) )
02167 {
02168 gCell = 0;
02169 return false;
02170 }
02171
02172
02173
02174 for (int i = 0; i < 5; ++i)
02175 {
02176 if ( !KSUtil::checkType( context, args[i], KSValue::DoubleType, true ) )
02177 {
02178 gCell = 0;
02179 return false;
02180 }
02181 }
02182
02183
02184
02185 double oldCol = args[1]->doubleValue();
02186 double oldRow = args[3]->doubleValue();
02187 kdDebug() << "Old values: Col: " << oldCol << ", Row: " << oldRow << endl;
02188
02189 KSpreadCell * cell;
02190 KSpreadSheet * sheet = ((KSpreadInterpreter *) context.interpreter() )->sheet();
02191
02192 KSpreadPoint point( extra[1]->stringValue() );
02193 KSpreadPoint point2( extra[3]->stringValue() );
02194 KSpreadPoint point3( extra[0]->stringValue() );
02195
02196 if ( ( args[1]->doubleValue() != args[2]->doubleValue() )
02197 || ( args[3]->doubleValue() != args[4]->doubleValue() ) )
02198 {
02199 cell = sheet->cellAt( point.pos.x(), point.pos.y() );
02200 cell->setValue( args[2]->doubleValue() );
02201 kdDebug() << "Setting value " << args[2]->doubleValue() << " on cell " << point.pos.x()
02202 << ", " << point.pos.y() << endl;
02203
02204 cell = sheet->cellAt( point2.pos.x(), point.pos.y() );
02205 cell->setValue( args[4]->doubleValue() );
02206 kdDebug() << "Setting value " << args[4]->doubleValue() << " on cell " << point2.pos.x()
02207 << ", " << point2.pos.y() << endl;
02208 }
02209
02210 KSpreadCell * cell1 = sheet->cellAt( point3.pos.x(), point3.pos.y() );
02211 cell1->calc( false );
02212
02213 double d = cell1->value().asFloat();
02214 kdDebug() << "Cell: " << point3.pos.x() << "; " << point3.pos.y() << " with value "
02215 << d << endl;
02216
02217 kdDebug() << "Resetting old values" << endl;
02218
02219 cell = sheet->cellAt( point.pos.x(), point.pos.y() );
02220 cell->setValue( oldCol );
02221
02222 cell = sheet->cellAt( point2.pos.x(), point2.pos.y() );
02223 cell->setValue( oldRow );
02224
02225 cell1->calc( false );
02226
02227
02228
02229 context.setValue( new KSValue( (double) d ) );
02230
02231 gCell = 0;
02232 return true;
02233 }
02234
02235
02236 bool kspreadfunc_subtotal( KSContext & context )
02237 {
02238 QValueList<KSValue::Ptr>& args = context.value()->listValue();
02239 QValueList<KSValue::Ptr>& extra = context.extraData()->listValue();
02240
02241 if ( !KSUtil::checkArgumentsCount( context, 2, "SUBTOTAL", true ) )
02242 return false;
02243
02244 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
02245 return false;
02246
02247
02248 QValueList<KSValue::Ptr> * list = new QValueList<KSValue::Ptr>;
02249 int function = args[0]->intValue();
02250
02251 KSValue * c = 0;
02252 KSpreadCell * cell = 0;
02253 KSpreadSheet * sheet = ((KSpreadInterpreter *) context.interpreter() )->sheet();
02254 KSpreadMap * map = ((KSpreadInterpreter *) context.interpreter() )->document()->map();
02255
02256 kdDebug() << "Range: " << extra[1]->stringValue() << endl;
02257
02258 KSpreadRange range ( extra[1]->stringValue(), map, sheet );
02259 if ( !range.isValid() )
02260 {
02261 KSpreadPoint point( extra[1]->stringValue(), map, sheet );
02262
02263 if ( !point.isValid() )
02264 return false;
02265
02266 range.range = QRect( point.pos.x(), point.pos.y(),
02267 point.pos.x(), point.pos.y() );
02268
02269 }
02270
02271 KSValue * l = new KSValue( KSValue::ListType );
02272 int count = 0;
02273 int countA = 0;
02274 double sum = 0.0;
02275 double max = 0.0;
02276
02277 if ( function == 6 )
02278 sum = 1.0;
02279
02280 int x = range.range.left();
02281 int y = range.range.top();
02282 int bottom = range.range.bottom();
02283
02284 for ( ; y <= bottom; ++y )
02285 {
02286 cell = sheet->cellAt( x, y );
02287 if ( cell->isDefault() || cell->text().find( "SUBTOTAL", 0, false ) != -1 )
02288 continue;
02289
02290 ++count;
02291 if ( cell->value().isNumber() )
02292 {
02293 ++countA;
02294 if ( function == 1 || function == 9 || function == 7 || function == 8
02295 || function == 10 || function == 11 )
02296 sum += cell->value().asFloat();
02297 else if ( function == 4 )
02298 {
02299 if ( countA == 1 )
02300 max = cell->value().asFloat();
02301 else
02302 if ( cell->value().asFloat() > max )
02303 max = cell->value().asFloat();
02304 }
02305 else if ( function == 5 )
02306 {
02307 if ( countA == 1 )
02308 max = cell->value().asFloat();
02309 else
02310 if ( cell->value().asFloat() < max )
02311 max = cell->value().asFloat();
02312 }
02313 else if ( function == 6 )
02314 sum *= cell->value().asFloat();
02315 }
02316
02317
02318 c = new KSValue( cell->value().asFloat() );
02319 l->listValue().append( c );
02320 }
02321 list->append ( l );
02322
02323
02324 double result = 0.0;
02325 double average = sum / countA;
02326
02327 switch( function )
02328 {
02329 case 1:
02330 context.setValue( new KSValue( average ) );
02331 break;
02332 case 2:
02333 context.setValue( new KSValue( count ) );
02334 break;
02335 case 3:
02336 context.setValue( new KSValue( countA ) );
02337 break;
02338 case 4:
02339 context.setValue( new KSValue( max ) );
02340 break;
02341 case 5:
02342 context.setValue( new KSValue( max ) );
02343 break;
02344 case 6:
02345 if ( countA == 0 )
02346 sum = 0.0;
02347 context.setValue( new KSValue( sum ) );
02348 break;
02349 case 7:
02350 kspreadfunc_stddev_helper( context, *list, result, average, false );
02351 context.setValue( new KSValue( sqrt( result / ((double) (countA - 1) ) ) ) );
02352 break;
02353 case 8:
02354 kspreadfunc_stddev_helper( context, *list, result, average, false );
02355 context.setValue( new KSValue( sqrt( result / countA ) ) );
02356 break;
02357 case 9:
02358 context.setValue( new KSValue( sum ) );
02359 break;
02360 case 10:
02361 kspreadfunc_variance_helper( context, *list, result, average, false );
02362 context.setValue( new KSValue( (double)(result / (countA - 1)) ) );
02363 break;
02364 case 11:
02365 kspreadfunc_variance_helper( context, *list, result, average, false );
02366 context.setValue( new KSValue( (double)(result / countA) ) );
02367 break;
02368 default:
02369 return false;
02370 }
02371
02372 return true;
02373 }
02374