Parent Directory
|
Revision Log
A couple of syntax issues.
1 # 2 # Extend differentiation to multiple variables 3 # Check differentiation for complex functions 4 # Do derivatives for norm and unit. 5 # 6 # Make shortcuts for getting numbers 1, 2, and sqrt, etc. 7 # 8 9 ################################################## 10 # 11 # Differentiate the formula in terms of the given variable(s) 12 # 13 sub Parser::D { 14 my $self = shift; 15 my $d; my @x = @_; my $x; 16 if (defined($x[0]) && $x[0] =~ m/^\d+$/) { 17 $d = shift(@x); 18 $self->Error("You can only specify one variable when you give a derivative count") 19 unless scalar(@x) <= 1; 20 return($self) if $d == 0; 21 } 22 if (scalar(@x) == 0) { 23 my @vars = keys(%{$self->{variables}}); 24 my $n = scalar(@vars); 25 if ($n == 0) { 26 return $self->new('0') if $self->{isNumber}; 27 $x = 'x'; 28 } else { 29 $self->Error("You must specify a variable to differentiate by") unless $n == 1; 30 $x = $vars[0]; 31 } 32 CORE::push(@x,$x); 33 } 34 @x = ($x[0]) x $d if $d; 35 my $f = $self->{tree}; 36 foreach $x (@x) { 37 return $self->new('0') unless defined $self->{variables}{$x}; 38 $f = $f->D($x); 39 } 40 return $self->new($f); 41 } 42 43 # 44 # Overridden by the classes that DO implement differentiation 45 # 46 sub Item::D { 47 my $self = shift; 48 my $type = ref($self); $type =~ s/.*:://; 49 $self->Error("Differentiation for '%s' is not implemented",$type); 50 } 51 52 53 ######################################################################### 54 55 sub Parser::BOP::comma::D {Item::D(shift)} 56 sub Parser::BOP::union::D {Item::D(shift)} 57 58 sub Parser::BOP::add::D { 59 my $self = shift; my $x = shift; 60 $self = $self->Item("BOP")->new( 61 $self->{equation},$self->{bop}, 62 $self->{lop}->D($x),$self->{rop}->D($x) 63 ); 64 return $self->reduce; 65 } 66 67 68 sub Parser::BOP::subtract::D { 69 my $self = shift; my $x = shift; 70 $self = $self->Item("BOP")->new( 71 $self->{equation},$self->{bop}, 72 $self->{lop}->D($x),$self->{rop}->D($x) 73 ); 74 return $self->reduce; 75 } 76 77 sub Parser::BOP::multiply::D { 78 my $self = shift; my $x = shift; 79 my $equation = $self->{equation}; 80 my $BOP = $self->Item("BOP"); 81 $self = 82 $BOP->new($equation,'+', 83 $BOP->new($equation,$self->{bop}, 84 $self->{lop}->D($x),$self->{rop}->copy($equation)), 85 $BOP->new($equation,$self->{bop}, 86 $self->{lop}->copy($equation),$self->{rop}->D($x)) 87 ); 88 return $self->reduce; 89 } 90 91 sub Parser::BOP::divide::D { 92 my $self = shift; my $x = shift; 93 my $equation = $self->{equation}; 94 my $BOP = $self->Item("BOP"); 95 $self = 96 $BOP->new($equation,$self->{bop}, 97 $BOP->new($equation,'-', 98 $BOP->new($equation,'*', 99 $self->{lop}->D($x),$self->{rop}->copy($equation)), 100 $BOP->new($equation,'*', 101 $self->{lop}->copy($equation),$self->{rop}->D($x)) 102 ), 103 $BOP->new($equation,'^',$self->{rop},$self->Item("Number")->new($equation,2)) 104 ); 105 return $self->reduce; 106 } 107 108 sub Parser::BOP::power::D { 109 my $self = shift; my $x = shift; 110 my $equation = $self->{equation}; 111 my $BOP = $self->Item("BOP"); 112 my $FN = $self->Item("Function"); 113 my $vars = $self->{rop}->getVariables; 114 if (defined($vars->{$x})) { 115 $vars = $self->{lop}->getVariables; 116 if (defined($vars->{$x})) { 117 $self = 118 $FN->new($equation,'exp', 119 [$BOP->new($equation,'*',$self->{rop}->copy($equation), 120 $FN->new($equation,'ln',[$self->{lop}->copy($equation)],0))]); 121 return $self->D($x); 122 } 123 $self = $BOP->new($equation,'*', 124 $FN->new($equation,'ln',[$self->{lop}->copy($equation)],0), 125 $BOP->new($equation,'*',$self->copy($equation),$self->{rop}->D($x)) 126 ); 127 } else { 128 $self = 129 $BOP->new($equation,'*', 130 $BOP->new($equation,'*', 131 $self->{rop}->copy($equation), 132 $BOP->new($equation,$self->{bop}, 133 $self->{lop}->copy($equation), 134 $BOP->new($equation,'-', 135 $self->{rop}->copy($equation), 136 $self->Item("Number")->new($equation,1) 137 ) 138 ) 139 ), 140 $self->{lop}->D($x) 141 ); 142 } 143 return $self->reduce; 144 } 145 146 sub Parser::BOP::cross::D {Item::D(shift)} 147 sub Parser::BOP::dot::D {Item::D(shift)} 148 sub Parser::BOP::underscore::D {Item::D(shift)} 149 150 ######################################################################### 151 152 sub Parser::UOP::plus::D { 153 my $self = shift; my $x = shift; 154 return $self->{op}->D($x) 155 } 156 157 sub Parser::UOP::minus::D { 158 my $self = shift; my $x = shift; 159 $self = $self->Item("UOP")->new($self->{equation},'u-',$self->{op}->D($x)); 160 return $self->reduce; 161 } 162 163 sub Parser::UOP::factorial::D {Item::D(shift)} 164 165 ######################################################################### 166 167 sub Parser::Function::D { 168 my $self = shift; 169 $self->Error("Differentiation of '%s' not implemented",$self->{name}); 170 } 171 172 sub Parser::Function::D_chain { 173 my $self = shift; my $x = $self->{params}[0]; 174 my $name = "D_" . $self->{name}; 175 $self = $self->Item("BOP")->new($self->{equation},'*',$self->$name($x->copy),$x->D(shift)); 176 return $self->reduce; 177 } 178 179 ############################# 180 181 sub Parser::Function::trig::D {Parser::Function::D_chain(@_)} 182 183 sub Parser::Function::trig::D_sin { 184 my $self = shift; my $x = shift; 185 return $self->Item("Function")->new($self->{equation},'cos',[$x]); 186 } 187 188 sub Parser::Function::trig::D_cos { 189 my $self = shift; my $x = shift; 190 my $equation = $self->{equation}; 191 return 192 $self->Item("UOP")->new($equation,'u-', 193 $self->Item("Function")->new($equation,'sin',[$x]) 194 ); 195 } 196 197 sub Parser::Function::trig::D_tan { 198 my $self = shift; my $x = shift; 199 my $equation = $self->{equation}; 200 return 201 $self->Item("BOP")->new($equation,'^', 202 $self->Item("Function")->new($equation,'sec',[$x]), 203 $self->Item("Number")->new($equation,2) 204 ); 205 } 206 207 sub Parser::Function::trig::D_cot { 208 my $self = shift; my $x = shift; 209 my $equation = $self->{equation}; 210 return 211 $self->Item("UOP")->new($equation,'u-', 212 $self->Item("BOP")->new($equation,'^', 213 $self->Item("Function")->new($equation,'csc',[$x]), 214 $self->Item("Number")->new($equation,2) 215 ) 216 ); 217 } 218 219 sub Parser::Function::trig::D_sec { 220 my $self = shift; my $x = shift; 221 my $equation = $self->{equation}; 222 my $FN = $self->Item("Function"); 223 return 224 $self->Item("BOP")->new($equation,'*', 225 $FN->new($equation,'sec',[$x]), 226 $FN->new($equation,'tan',[$x]) 227 ); 228 } 229 230 sub Parser::Function::trig::D_csc { 231 my $self = shift; my $x = shift; 232 my $equation = $self->{equation}; 233 my $FN = $self->Item("Function"); 234 return 235 $self->Item("UOP")->new($equation,'u-', 236 $self->Item("BOP")->new($equation,'*', 237 $FN->new($equation,'csc',[$x]), 238 $FN->new($equation,'cot',[$x]) 239 ) 240 ); 241 } 242 243 sub Parser::Function::trig::D_asin { 244 my $self = shift; my $x = shift; 245 my $equation = $self->{equation}; 246 my $BOP = $self->Item("BOP"); 247 my $NUM = $self->Item("Number"); 248 return 249 $BOP->new($equation,'/', 250 $NUM->new($equation,1), 251 $self->Item("Function")->new($equation,'sqrt',[ 252 $BOP->new($equation,'-', 253 $NUM->new($equation,1), 254 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 255 )] 256 ) 257 ); 258 } 259 260 sub Parser::Function::trig::D_acos { 261 my $self = shift; my $x = shift; 262 my $equation = $self->{equation}; 263 my $BOP = $self->Item("BOP"); 264 my $NUM = $self->Item("Number"); 265 return 266 $self->Item("UOP")->new($equation,'u-', 267 $BOP->new($equation,'/', 268 $NUM->new($equation,1), 269 $self->Item("Function")->new($equation,'sqrt',[ 270 $BOP->new($equation,'-', 271 $NUM->new($equation,1), 272 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 273 )] 274 ) 275 ) 276 ); 277 } 278 279 sub Parser::Function::trig::D_atan { 280 my $self = shift; my $x = shift; 281 my $equation = $self->{equation}; 282 my $BOP = $self->Item("BOP"); 283 my $NUM = $self->Item("Number"); 284 return 285 $BOP->new($equation,'/', 286 $NUM->new($equation,1), 287 $BOP->new($equation,'+', 288 $NUM->new($equation,1), 289 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 290 ) 291 ); 292 } 293 294 sub Parser::Function::trig::D_acot { 295 my $self = shift; my $x = shift; 296 my $equation = $self->{equation}; 297 my $BOP = $self->Item("BOP"); 298 my $NUM = $self->Item("Number"); 299 return 300 $self->Item("UOP")->new($equation,'u-', 301 $BOP->new($equation,'/', 302 $NUM->new($equation,1), 303 $BOP->new($equation,'+', 304 $NUM->new($equation,1), 305 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 306 ) 307 ) 308 ); 309 } 310 311 sub Parser::Function::trig::D_asec { 312 my $self = shift; my $x = shift; 313 my $equation = $self->{equation}; 314 my $BOP = $self->Item("BOP"); 315 my $NUM = $self->Item("Number"); 316 my $FN = $self->Item("Function"); 317 return 318 $BOP->new($equation,'/', 319 $NUM->new($equation,1), 320 $BOP->new($equation,'*', 321 $FN->new($equation,'abs',[$x]), 322 $FN->new($equation,'sqrt',[ 323 $BOP->new($equation,'-', 324 $BOP->new($equation,'^',$x,$NUM->new($equation,2)), 325 $NUM->new($equation,1) 326 )] 327 ) 328 ) 329 ); 330 } 331 332 sub Parser::Function::trig::D_acsc { 333 my $self = shift; my $x = shift; 334 my $equation = $self->{equation}; 335 my $BOP = $self->Item("BOP"); 336 my $NUM = $self->Item("Number"); 337 my $FN = $self->Item("Function"); 338 return 339 $self->Item("UOP")->new($equation,'u-', 340 $BOP->new($equation,'/', 341 $NUM->new($equation,1), 342 $BOP->new($equation,'*', 343 $FN->new($equation,'abs',[$x]), 344 $FN->new($equation,'sqrt',[ 345 $BOP->new($equation,'-', 346 $BOP->new($equation,'^',$x,$NUM->new($equation,2)), 347 $NUM->new($equation,1) 348 )] 349 ) 350 ) 351 ) 352 ); 353 } 354 355 356 ############################# 357 358 sub Parser::Function::hyperbolic::D {Parser::Function::D_chain(@_)} 359 360 sub Parser::Function::hyperbolic::D_sinh { 361 my $self = shift; my $x = shift; 362 return $self->Item("Function")->new($self->{equation},'cosh',[$x]); 363 } 364 365 sub Parser::Function::hyperbolic::D_cosh { 366 my $self = shift; my $x = shift; 367 return $self->Item("Function")->new($self->{equation},'sinh',[$x]); 368 } 369 370 sub Parser::Function::hyperbolic::D_tanh { 371 my $self = shift; my $x = shift; 372 my $equation = $self->{equation}; 373 return 374 $self->Item("BOP")->new($equation,'^', 375 $self->Item("Function")->new($equation,'sech',[$x]), 376 $self->Item("Number")->new($equation,2) 377 ); 378 } 379 380 sub Parser::Function::hyperbolic::D_coth { 381 my $self = shift; my $x = shift; 382 my $equation = $self->{equation}; 383 return 384 $self->Item("UOP")->new($equation,'u-', 385 $self->Item("BOP")->new($equation,'^', 386 $self->Item("Function")->new($equation,'csch',[$x]), 387 $self->Item("Number")->new($equation,2) 388 ) 389 ); 390 } 391 392 sub Parser::Function::hyperbolic::D_sech { 393 my $self = shift; my $x = shift; 394 my $equation = $self->{equation}; 395 my $FN = $self->Item("Function"); 396 return 397 $self->Item("UOP")->new($equation,'u-', 398 $self->Item("BOP")->new($equation,'*', 399 $FN->new($equation,'sech',[$x]), 400 $FN->new($equation,'tanh',[$x]) 401 ) 402 ); 403 } 404 405 sub Parser::Function::hyperbolic::D_csch { 406 my $self = shift; my $x = shift; 407 my $equation = $self->{equation}; 408 my $FN = $self->Item("Function"); 409 return 410 $self->Item("UOP")->new($equation,'u-', 411 $self->Item("BOP")->new($equation,'*', 412 $FN->new($equation,'csch',[$x]), 413 $FN->new($equation,'coth',[$x]) 414 ) 415 ); 416 } 417 418 sub Parser::Function::hyperbolic::D_asinh { 419 my $self = shift; my $x = shift; 420 my $equation = $self->{equation}; 421 my $BOP = $self->Item("BOP"); 422 my $NUM = $self->Item("Number"); 423 return 424 $BOP->new($equation,'/', 425 $NUM->new($equation,1), 426 $self->Item("Function")->new($equation,'sqrt',[ 427 $BOP->new($equation,'+', 428 $NUM->new($equation,1), 429 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 430 )] 431 ) 432 ); 433 } 434 435 sub Parser::Function::hyperbolic::D_acosh { 436 my $self = shift; my $x = shift; 437 my $equation = $self->{equation}; 438 my $BOP = $self->Item("BOP"); 439 my $NUM = $self->Item("Number"); 440 return 441 $BOP->new($equation,'/', 442 $NUM->new($equation,1), 443 $self->Item("Function")->new($equation,'sqrt',[ 444 $BOP->new($equation,'-', 445 $BOP->new($equation,'^',$x,$NUM->new($equation,2)), 446 $NUM->new($equation,1) 447 )] 448 ) 449 ); 450 } 451 452 sub Parser::Function::hyperbolic::D_atanh { 453 my $self = shift; my $x = shift; 454 my $equation = $self->{equation}; 455 my $BOP = $self->Item("BOP"); 456 my $NUM = $self->Item("Number"); 457 return 458 $BOP->new($equation,'/', 459 $NUM->new($equation,1), 460 $BOP->new($equation,'-', 461 $NUM->new($equation,1), 462 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 463 ) 464 ); 465 } 466 467 sub Parser::Function::hyperbolic::D_acoth { 468 my $self = shift; my $x = shift; 469 my $equation = $self->{equation}; 470 my $BOP = $self->Item("BOP"); 471 my $NUM = $self->Item("Number"); 472 return 473 $BOP->new($equation,'/', 474 $NUM->new($equation,1), 475 $BOP->new($equation,'-', 476 $NUM->new($equation,1), 477 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 478 ) 479 ); 480 } 481 482 sub Parser::Function::hyperbolic::D_asech { 483 my $self = shift; my $x = shift; 484 my $equation = $self->{equation}; 485 my $BOP = $self->Item("BOP"); 486 my $NUM = $self->Item("Number"); 487 return 488 $self->Item("UOP")->new($equation,'u-', 489 $BOP->new($equation,'/', 490 $NUM->new($equation,1), 491 $BOP->new($equation,'*', 492 $x, 493 $self->Item("Function")->new($equation,'sqrt',[ 494 $BOP->new($equation,'-', 495 $NUM->new($equation,1), 496 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 497 )] 498 ) 499 ) 500 ) 501 ); 502 } 503 504 sub Parser::Function::hyperbolic::D_acsch { 505 my $self = shift; my $x = shift; 506 my $equation = $self->{equation}; 507 my $BOP = $self->Item("BOP"); 508 my $NUM = $self->Item("Number"); 509 my $FN = $self->Item("Function"); 510 return 511 $self->Item("UOP")->new($equation,'u-', 512 $BOP->new($equation,'/', 513 $NUM->new($equation,1), 514 $BOP->new($equation,'*', 515 $FN->new($equation,'abs',[$x]), 516 $FN->new($equation,'sqrt',[ 517 $BOP->new($equation,'+', 518 $NUM->new($equation,1), 519 $BOP->new($equation,'^',$x,$NUM->new($equation,2)) 520 )] 521 ) 522 ) 523 ) 524 ); 525 } 526 527 528 ############################# 529 530 sub Parser::Function::numeric::D {Parser::Function::D_chain(@_)} 531 532 sub Parser::Function::numeric::D_ln { 533 my $self = shift; my $x = shift; 534 my $equation = $self->{equation}; 535 return $self->Item("BOP")->new($equation,'/',$self->Item("Number")->new($equation,1),$x); 536 } 537 538 sub Parser::Function::numeric::D_log { 539 my $self = $_[0]; 540 my $base10 = $self->{equation}{context}{flags}{useBaseTenLog}; 541 if ($base10) {return D_log10(@_)} else {return D_ln(@_)} 542 } 543 544 sub Parser::Function::numeric::D_log10 { 545 my $self = shift; my $x = shift; 546 my $equation = $self->{equation}; 547 my $BOP = $self->Item("BOP"); 548 my $NUM = $self->Item("Number"); 549 return 550 $BOP->new($equation,'/', 551 $NUM->new($equation,1), 552 $BOP->new($equation,'*', 553 $NUM->new($equation,CORE::log(10)), $x 554 ) 555 ); 556 } 557 558 sub Parser::Function::numeric::D_exp { 559 my $self = shift; 560 return $self->copy(); 561 } 562 563 sub Parser::Function::numeric::D_sqrt { 564 my $self = shift; 565 my $equation = $self->{equation}; 566 my $BOP = $self->Item("BOP"); 567 my $NUM = $self->Item("Number"); 568 return 569 $BOP->new($equation,'/', 570 $NUM->new($equation,1), 571 $BOP->new($equation,'*', 572 $NUM->new($equation,2), 573 $self->copy 574 ) 575 ); 576 } 577 578 sub Parser::Function::numeric::D_abs { 579 my $self = shift; my $x = shift; 580 my $equation = $self->{equation}; 581 return $self->Item("BOP")->new($equation,'/',$x,$self->copy); 582 } 583 584 sub Parser::Function::numeric::D_int {Parser::Function::D(@_)} 585 sub Parser::Function::numeric::D_sgn {Parser::Function::D(@_)} 586 587 ######################################################################### 588 589 sub Parser::List::D { 590 my $self = shift; my $x = shift; 591 $self = $self->copy($self->{equation}); 592 foreach my $f (@{$self->{coords}}) {$f = $f->D($x)} 593 return $self->reduce; 594 } 595 596 597 sub Parser::List::Interval::D { 598 my $self = shift; 599 $self->Error("Can't differentiate intervals"); 600 } 601 602 sub Parser::List::AbsoluteValue::D { 603 my $self = shift; my $x = $self->{coords}[0]->copy; 604 my $equation = $self->{equation}; 605 my $BOP = $self->Item("BOP"); 606 return 607 $BOP->new($equation,"*", 608 $BOP->new($equation,'/', $x, $self->copy), 609 $x->D(shift), 610 ); 611 } 612 613 614 ######################################################################### 615 616 sub Parser::Number::D { 617 my $self = shift; 618 $self->Item("Number")->new($self->{equation},0); 619 } 620 621 ######################################################################### 622 623 sub Parser::Complex::D { 624 my $self = shift; 625 $self->Item("Number")->new($self->{equation},0); 626 } 627 628 ######################################################################### 629 630 sub Parser::Constant::D { 631 my $self = shift; 632 $self->Item("Number")->new($self->{equation},0); 633 } 634 635 ######################################################################### 636 637 sub Parser::Value::D { 638 my $self = shift; my $x = shift; my $equation = $self->{equation}; 639 return $self->Item("Value")->new($equation,$self->{value}->D($x)); 640 } 641 642 sub Value::D { 643 my $self = shift; my $x = shift; 644 my @coords = $self->value; 645 foreach my $n (@coords) 646 {if (ref($n) eq "") {$n = 0} else {$n = $n->D($x)->value}} 647 return $self->new(@coords); 648 } 649 650 sub Value::List::D { 651 my $self = shift; my $x = shift; 652 my @coords = $self->value; 653 foreach my $n (@coords) 654 {if (ref($n) eq "") {$n = 0} else {$n = $n->D($x)}} 655 return $self->new([@coords]); 656 } 657 658 sub Value::Interval::D { 659 shift; shift; my $self = shift; 660 $self->Error("Can't differentiate intervals"); 661 } 662 663 sub Value::Set::D { 664 shift; shift; my $self = shift; 665 $self->Error("Can't differentiate sets"); 666 } 667 668 sub Value::Union::D { 669 shift; shift; my $self = shift; 670 $self->Error("Can't differentiate unions"); 671 } 672 673 ######################################################################### 674 675 sub Parser::Variable::D { 676 my $self = shift; my $x = shift; 677 my $d = ($self->{name} eq $x)? 1: 0; 678 return $self->Item("Number")->new($self->{equation},$d); 679 } 680 681 ######################################################################### 682 683 sub Parser::String::D { 684 my $self = shift; 685 $self->Item("Number")->new($self->{equation},0); 686 } 687 688 ######################################################################### 689 690 package Parser::Differentiation; 691 our $loaded = 1; 692 693 ######################################################################### 694 695 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |