1// 2// EMResponder.m 3// EdenMath 4// 5// Created by admin on Thu Feb 21 2002. 6// Copyright (c) 2002-2004 Edenwaith. All rights reserved. 7// 8 9#import "EMResponder.h" 10 11#include <math.h> 12#include <stdlib.h> 13 14#ifdef GNUSTEP 15#include <time.h> 16#endif 17 18@implementation EMResponder 19 20 21// ------------------------------------------------------- 22// (id) init 23// ------------------------------------------------------- 24- (id) init 25{ 26 current_value = 0.0; 27 previous_value = 0.0; 28 op_type = NO_OP; 29 angle_type = DEGREE; 30 e_value = M_E; // 2.7182818285 31 trailing_digits = 0; 32 isNewDigit = YES; 33 34 return self; 35} 36 37// ------------------------------------------------------- 38// (double) getCurrentValue 39// Simple return function which returns the current 40// value 41// ------------------------------------------------------- 42- (double) getCurrentValue 43{ 44 return current_value; 45} 46 47 48// ------------------------------------------------------- 49// (int) getTrailingDigits 50// Simple return function which returns the number of 51// trailing digits on the currently displayed number 52// so the proper amount of precision can be displayed. 53// Limit the number of trailing digits precision so odd 54// errors don't occur. 55// ------------------------------------------------------- 56- (int) getTrailingDigits 57{ 58 if (trailing_digits == 0) 59 { 60 trailing_digits = 0; 61 } 62 else if (trailing_digits > 10) 63 { 64 trailing_digits = 10; 65 } 66 67 return trailing_digits; 68} 69 70// ------------------------------------------------------- 71// (void) setCurrentValue:(double)num 72// ------------------------------------------------------- 73- (void) setCurrentValue:(double)num 74{ 75 current_value = num; 76} 77 78 79// ------------------------------------------------------- 80// (void) setState:(NSDictionary *)stateDictionary 81// ------------------------------------------------------- 82- (void)setState:(NSDictionary *)stateDictionary 83{ 84 current_value = [[stateDictionary objectForKey: @"current_value"] doubleValue]; 85 previous_value = [[stateDictionary objectForKey: @"previous_value"] doubleValue]; 86 op_type = [[stateDictionary objectForKey: @"op_type"] intValue]; 87 trailing_digits = [[stateDictionary objectForKey: @"trailing_digits"] intValue]; 88 isNewDigit = [[stateDictionary objectForKey: @"isNewDigit"] boolValue]; 89} 90 91// ------------------------------------------------------- 92// (NSDictionary *) state 93// ------------------------------------------------------- 94- (NSDictionary *)state 95{ 96 NSDictionary *stateDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 97 [NSNumber numberWithDouble: current_value], @"current_value", 98 [NSNumber numberWithDouble: previous_value], @"previous_value", 99 [NSNumber numberWithInt: op_type], @"op_type", 100 [NSNumber numberWithInt: trailing_digits], @"trailing_digits", 101 [NSNumber numberWithBool: isNewDigit], @"isNewDigit", 102 nil]; 103 return stateDictionary; 104} 105 106// ------------------------------------------------------- 107// (void)newDigit:(int)digit 108// ------------------------------------------------------- 109- (void)newDigit:(int)digit 110{ 111 112 if (isNewDigit) 113 { 114 previous_value = current_value; 115 isNewDigit = NO; 116 current_value = digit; 117 } 118 else 119 { 120 BOOL negative = NO; 121 if (current_value < 0) 122 { 123 current_value = - current_value; 124 negative = YES; 125 } 126 127 if (trailing_digits == 0) 128 { 129 current_value = current_value * 10 + digit; 130 } 131 else 132 { 133 current_value = current_value + (digit/pow(10.0, trailing_digits)); 134 135 trailing_digits++; 136 } 137 138 if (negative == YES) 139 { 140 current_value = - current_value; 141 } 142 } 143} 144 145// ------------------------------------------------------- 146// (void) period 147// ------------------------------------------------------- 148- (void)period 149{ 150 if (isNewDigit) 151 { 152 current_value = 0.0; 153 isNewDigit = NO; 154 } 155 if (trailing_digits == 0) 156 { 157 trailing_digits = 1; 158 } 159} 160 161// ------------------------------------------------------- 162// (void) pi 163// Display the constant pi (3.141592653589793) 164// ------------------------------------------------------- 165- (void) pi 166{ 167 current_value = M_PI; 168 trailing_digits = 0; 169 isNewDigit = YES; 170} 171 172// ------------------------------------------------------- 173// (void) trig_constant 174// Display the constant pi (3.141592653589793) 175// ------------------------------------------------------- 176- (void) trig_constant: (double) trig_const 177{ 178 current_value = trig_const; 179 trailing_digits = 0; 180 isNewDigit = YES; 181} 182 183// ------------------------------------------------------- 184// (void) e 185// Display the constant e (2.718281828459045) 186// ------------------------------------------------------- 187- (void)e 188{ 189 current_value = M_E; 190 trailing_digits = 0; 191 isNewDigit = YES; 192} 193 194// ------------------------------------------------------- 195// (void) clear 196// clear the displayField and reset several variables 197// ------------------------------------------------------- 198- (void) clear 199{ 200 current_value = 0.0; 201 previous_value = 0.0; 202 op_type = NO_OP; 203 trailing_digits = 0; 204 isNewDigit = YES; 205} 206 207// ------------------------------------------------------- 208// (void)operation:(OpType)new_op_type 209// ------------------------------------------------------- 210- (void)operation:(OpType)new_op_type 211{ 212 if (op_type == NO_OP) 213 { 214 previous_value = current_value; 215 isNewDigit = YES; 216 op_type = new_op_type; 217 trailing_digits = 0; 218 } 219 else 220 { 221 // cascading operations 222 [self enter]; // calculate previous value, first 223 previous_value = current_value; 224 isNewDigit = YES; 225 op_type = new_op_type; 226 trailing_digits = 0; 227 } 228} 229 230// ------------------------------------------------------- 231// (void)enter 232// For binary operators (+, -, x, /, etc.), calculate 233// the value and place into current_value 234// ------------------------------------------------------- 235- (void)enter 236{ 237 switch (op_type) 238 { 239 case NO_OP: 240 break; 241 case ADD_OP: 242 current_value = previous_value + current_value; 243 break; 244 case SUBTRACT_OP: 245 current_value = previous_value - current_value; 246 break; 247 case MULTIPLY_OP: 248 current_value = previous_value * current_value; 249 break; 250 case DIVIDE_OP: 251 if (current_value != 0.0) 252 { 253 current_value = previous_value / current_value; 254 } 255 break; 256 case EXPONENT_OP: // x^y 257 current_value = pow(previous_value, current_value); 258 break; 259 case XROOT_OP: // y�x 260 current_value = pow(previous_value, 1/current_value); 261 break; 262 case MOD_OP: 263 current_value = (int)previous_value % (int)current_value; 264 break; 265 case EE_OP: 266 current_value = previous_value * pow(10, current_value); 267 break; 268 case NPR_OP: // n!/(n-r)! 269 current_value = [self factorial:previous_value] / [self factorial:(previous_value - current_value)]; 270 break; 271 case NCR_OP: // n!/(r! * (n-r)!) 272 current_value = [self factorial:previous_value] / ([self factorial:current_value] * [self factorial:(previous_value - current_value)]); 273 break; 274 } 275 previous_value = 0.0; 276 op_type = NO_OP; 277 trailing_digits = 0; 278 isNewDigit = YES; 279} 280 281// ===================================================================================== 282// ALGEBRAIC FUNCTIONS 283// ===================================================================================== 284 285// ------------------------------------------------------- 286// (void) reverse_sign 287// ------------------------------------------------------- 288- (void) reverse_sign 289{ 290 current_value = - current_value; 291} 292 293// ------------------------------------------------------- 294// (void)percentage 295// ------------------------------------------------------- 296- (void)percentage 297{ 298 current_value = current_value * 0.01; 299 isNewDigit = YES; 300 trailing_digits = 0; 301} 302 303// ------------------------------------------------------- 304// (void) squared 305// ------------------------------------------------------- 306- (void) squared 307{ 308 current_value = pow(current_value, 2); 309 isNewDigit = YES; 310} 311 312// ------------------------------------------------------- 313// (void) cubed 314// ------------------------------------------------------- 315- (void) cubed 316{ 317 current_value = pow(current_value, 3); 318 isNewDigit = true; 319} 320 321// ------------------------------------------------------- 322// (void) square_root 323// ------------------------------------------------------- 324- (void) square_root 325{ 326 if (current_value >= 0.0) 327 { 328 current_value = sqrt(current_value); 329 } 330 331 isNewDigit = YES; 332} 333 334// ------------------------------------------------------- 335// (void) cubed_root 336// ------------------------------------------------------- 337- (void)cubed_root 338{ 339 //if (current_value >= 0.0) 340 //{ 341 current_value = pow(current_value, 0.3333333333333333); 342 //} 343 344 isNewDigit = YES; 345} 346 347// ------------------------------------------------------- 348// (void) ln 349// natural log 350// ------------------------------------------------------- 351- (void)ln 352{ 353 if (current_value > 0.0) 354 { 355 current_value = log(current_value); 356 } 357 358 isNewDigit = YES; 359} 360 361// ------------------------------------------------------- 362// (void) cubed_root 363// logarithm base 10 364// ------------------------------------------------------- 365- (void)logarithm 366{ 367 if (current_value > 0.0) 368 { 369 current_value = log10(current_value); 370 } 371 372 isNewDigit = YES; 373} 374 375// ------------------------------------------------------- 376// (void) factorial 377// This new function replaces the old factorial function 378// with a gamma function. For more information, read the 379// lgamma man page or 380// http://www.gnu.org/software/libc/manual/html_node/Special-Functions.html 381// Version: 8. March 2004 23:40 382// ------------------------------------------------------- 383- (void) factorial 384{ 385 double lg; 386 387 // 170.5 seems to be the max value which EdenMath can handle 388 if (current_value < 170.5) 389 { 390 lg = lgamma(current_value+1.0); 391 current_value = signgam*exp(lg); /* signgam is a predefined variable */ 392 } 393 394 trailing_digits = 0; // this allows for more precise decimal precision 395 isNewDigit = YES; 396 397} 398 399// ------------------------------------------------------- 400// (double) factorial: (double) n 401// This is required for the permutations and combinations 402// calls. 403// Version: 9. March 2004 23:48 404// ------------------------------------------------------- 405- (double) factorial: (double) n 406{ 407 double lg; 408 409 // 170.5 seems to be the max value which EdenMath can handle 410 if (n < 170.5) 411 { 412 lg = lgamma(n+1.0); 413 n = signgam*exp(lg); 414 } 415 416 return (n); 417 418} 419 420// ------------------------------------------------------- 421// (void) powerE 422// e^x 423// M_E is a constant hidden somewhere in the included 424// libraries 425// ------------------------------------------------------- 426- (void) powerE 427{ 428 current_value = pow(M_E, current_value); 429 isNewDigit = YES; 430} 431 432// ------------------------------------------------------- 433// (void) 10^x 434// ------------------------------------------------------- 435- (void) power10 436{ 437 current_value = pow(10, current_value); 438 isNewDigit = YES; 439} 440 441// ------------------------------------------------------- 442// (void) inverse 443// ------------------------------------------------------- 444- (void)inverse 445{ 446 if (current_value != 0.0) 447 { 448 current_value = 1/current_value; 449 } 450 451 isNewDigit = YES; 452} 453 454// ===================================================================================== 455// TRIGOMETRIC FUNCTIONS 456// ===================================================================================== 457 458// ------------------------------------------------------- 459// (void) setAngleType:(AngleType)aType 460// Modify the type of angles using degrees, radians, or 461// gradients. EM 1.1.1 reduced this code down to one 462// line, eliminating multiple IF-ELSE statements. 463// ------------------------------------------------------- 464// Version: 31. May 2003 465// ------------------------------------------------------- 466- (void)setAngleType:(AngleType)aType 467{ 468 angle_type = aType; 469} 470 471// ------------------------------------------------------- 472// (double)deg_to_rad:(double)degrees 473// Convert from degrees to radians 474// ------------------------------------------------------- 475- (double)deg_to_rad:(double)degrees 476{ 477 double radians = 0.0; 478 radians = degrees * M_PI / 180; 479 480 return radians; 481} 482 483// ------------------------------------------------------- 484// (double)rad_to_deg:(double)radians 485// Convert from radians to degrees 486// ------------------------------------------------------- 487// Created: 31. May 2003 488// Version: 31. May 2003 489// ------------------------------------------------------- 490- (double)rad_to_deg:(double)radians 491{ 492 double degrees = 0.0; 493 degrees = radians * 180 / M_PI; 494 495 return degrees; 496} 497 498// ------------------------------------------------------- 499// (double)grad_to_rad:(double)gradients 500// Convert from gradients to radians 501// http://www.onlineconversion.com/angles.htm 502// 1 gradient = 0.015707963267948966192 radians 503// 1 gradient = 0.9 degrees 504// Created higher precision for the conversion so 505// Tan(50g) would equal 1. Otherwise, if the conversion 506// isn't precise enough, it comes out to be 1.000003672. 507// ------------------------------------------------------- 508// Version: 31. May 2003 509// ------------------------------------------------------- 510- (double)grad_to_rad:(double)gradients 511{ 512 double radians = 0.0; 513 radians = gradients * 0.015707963267948966192; 514 515 return radians; 516} 517 518// ------------------------------------------------------- 519// (double)rad_to_grad:(double)radians 520// Convert from radians to gradients 521// http://www.onlineconversion.com/angles.htm 522// 1 gradient = 0.015707963267948966192 radians 523// 1 gradient = 0.9 degrees 524// ------------------------------------------------------- 525// Created: 31. May 2003 526// Version: 31. May 2003 527// ------------------------------------------------------- 528- (double)rad_to_grad:(double)radians 529{ 530 double gradients = 0.0; 531 gradients = radians / 0.015707963267948966192; 532 533 return gradients; 534} 535 536// ------------------------------------------------------- 537// (void) sine 538// ------------------------------------------------------- 539- (void)sine 540{ 541 if (angle_type == DEGREE) 542 { 543 current_value = [self deg_to_rad:current_value]; 544 } 545 else if (angle_type == GRADIENT) 546 { 547 current_value = [self grad_to_rad:current_value]; 548 } 549 550 current_value = sin(current_value); 551 isNewDigit = YES; 552} 553 554// ------------------------------------------------------- 555// (void) cosine 556// ------------------------------------------------------- 557- (void)cosine 558{ 559 if (angle_type == DEGREE) 560 { 561 current_value = [self deg_to_rad:current_value]; 562 } 563 else if (angle_type == GRADIENT) 564 { 565 current_value = [self grad_to_rad:current_value]; 566 } 567 568 current_value = cos(current_value); 569 isNewDigit = YES; 570} 571 572// ------------------------------------------------------- 573// (void) tangent 574// ------------------------------------------------------- 575- (void)tangent 576{ 577 if (angle_type == DEGREE) 578 { 579 current_value = [self deg_to_rad:current_value]; 580 } 581 else if (angle_type == GRADIENT) 582 { 583 current_value = [self grad_to_rad:current_value]; 584 } 585 586 if ( ( current_value == M_PI/2) || (current_value == 3 * M_PI / 2) || 587 ( current_value == - M_PI/2) || (current_value == -3 * M_PI / 2) ) 588 { 589 NSBeep(); 590 NSRunAlertPanel(@"Warning", @"Tan cannot calculate values of �/2 or 3�/2", 591 @"OK", nil, nil); 592 } 593 else // otherwise, tan will still be calculated on �/2 or 3�/2, which is wrong. 594 { 595 current_value = tan(current_value); 596 } 597 598 isNewDigit = YES; 599} 600 601// ------------------------------------------------------- 602// (void) arcsine 603// ------------------------------------------------------- 604// Version: 31. May 2003 605// ------------------------------------------------------- 606- (void)arcsine 607{ 608 current_value = asin(current_value); 609 isNewDigit = YES; 610 611 if (angle_type == DEGREE) 612 { 613 current_value = [self rad_to_deg:current_value]; 614 } 615 else if (angle_type == GRADIENT) 616 { 617 current_value = [self rad_to_grad:current_value]; 618 } 619} 620 621// ------------------------------------------------------- 622// (void) arccosine 623// ------------------------------------------------------- 624// Version: 31. May 2003 625// ------------------------------------------------------- 626- (void)arccosine 627{ 628 current_value = acos(current_value); 629 isNewDigit = YES; 630 631 if (angle_type == DEGREE) 632 { 633 current_value = [self rad_to_deg:current_value]; 634 } 635 else if (angle_type == GRADIENT) 636 { 637 current_value = [self rad_to_grad:current_value]; 638 } 639} 640 641// ------------------------------------------------------- 642// (void) arctangent 643// ------------------------------------------------------- 644// Version: 31. May 2003 645// ------------------------------------------------------- 646- (void)arctangent 647{ 648 current_value = atan(current_value); 649 isNewDigit = YES; 650 651 if (angle_type == DEGREE) 652 { 653 current_value = [self rad_to_deg:current_value]; 654 } 655 else if (angle_type == GRADIENT) 656 { 657 current_value = [self rad_to_grad:current_value]; 658 } 659} 660 661// ===================================================================================== 662// PROBABILITY FUNCTIONS 663// The Probability and Combination functions are in the enter function since they 664// act as binary operators 665// ===================================================================================== 666 667// ------------------------------------------------------- 668// (void) generate_random_num 669// ------------------------------------------------------- 670- (double) generate_random_num 671{ 672 static int seeded = 0; 673 double value = 0.0; 674 675 if (seeded == 0) 676 { 677 srand((unsigned)time((time_t *)NULL)); 678 seeded = 1; 679 } 680 681 value = rand(); 682 683 return value; 684} 685 686// ------------------------------------------------------- 687// (void) random_num 688// ------------------------------------------------------- 689- (void) random_num 690{ 691 current_value = [self generate_random_num]; 692 isNewDigit = YES; 693} 694 695@end 696