Changeset 174 for trunk/src/helpers/math.c
- Timestamp:
- Jun 14, 2002, 2:20:11 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/math.c
r88 r174 67 67 68 68 } 69 70 /* binary GCD alg. Based on following facts.71 If N and M are even, then gcd(N,M) = 2 * gcd (N/2, M/2)72 If N even and M odd, then gcd(N,M) = gcd(N/2, M)73 If N,M odd, then |N-M|<max(N,M) thus guaranteeing that74 we can use gcd(N,M) = gcd(N-M,M) to reduce.75 fact: a&1 is 1 iff a is odd. Mult. and Div. by 2 more efficiently76 implemented as shift-left 1 and shift-right 1 resp.77 78 Found at http://remus.rutgers.edu/~rhoads/Code/int_gcd.c79 */80 81 /* long gcd( long a, long b)82 {83 int t;84 85 if (a < 0) a = -a;86 if (!b) return a;87 if (b < 0) b = -b;88 if (!a) return b;89 t = 0;90 while (! ((a|b) & 1)) {a >>= 1; b >>= 1; ++t;}91 while (! (a&1)) a >>= 1;92 while (! (b&1)) b >>= 1;93 while (a != b)94 {95 if (a > b)96 {97 a -= b;98 do {a >>= 1;} while (! (a&1));99 }100 else {101 b -= a;102 do {b >>= 1;} while (! (b&1));103 }104 }105 return(a<<t); */106 69 107 70 /* … … 393 356 } 394 357 395 /* typedef struct _PRIMEDATA 396 { 397 LINKLIST llPrimes; 398 int iCurrentInt; 399 } PRIMEDATA, *PPRIMEDATA; 400 401 402 typedef struct _PRIMEENTRY 403 { 404 int iPrime; 405 int iLowestPowerFound; 406 // lowest power that was found for this prime number; 407 // if 0, a prime was previously present and then not 408 // for a later prime 409 int iLastInt; 410 } PRIMEENTRY, *PPRIMEENTRY; */ 411 412 /* 413 *@@ GCDMultiCallbackCreate: 414 * first callback for mathGCDMulti. 415 */ 416 417 /* int XWPENTRY GCDMultiCallbackCreate(int n, // in: prime 418 int p, // in: power 419 void *pUser) // in: user param, here root of tree 420 { 421 // see if we had this 422 PPRIMEDATA pData = (PPRIMEDATA)pUser; 423 PLISTNODE pNode; 424 PPRIMEENTRY pEntry; 425 for (pNode = lstQueryFirstNode(&pData->llPrimes); 426 pNode; 427 pNode = pNode->pNext) 428 { 429 pEntry = (PPRIMEENTRY)pNode->pItemData; 430 if (pEntry->iPrime == n) 431 { 432 // mark this as processed so we can later see 433 // if the current integer had this prime factor 434 // at all 435 pEntry->iLastInt = pData->iCurrentInt; 436 437 // printf(" %d^%d", n, p); 438 439 // and stop 440 return 0; 441 } 442 } 443 444 // no entry for this yet: 445 // printf(" %d^%d", n, p); 446 pEntry = NEW(PRIMEENTRY); 447 pEntry->iPrime = n; 448 pEntry->iLowestPowerFound = p; 449 pEntry->iLastInt = pData->iCurrentInt; 450 lstAppendItem(&pData->llPrimes, pEntry); 451 452 return (0); 453 } */ 454 455 /* 456 *@@ GCDMultiCallbackLowest: 457 * second callback for mathGCDMulti. 458 */ 459 460 /* int XWPENTRY GCDMultiCallbackLowest(int n, // in: prime 461 int p, // in: power 462 void *pUser) // in: user param, here root of tree 463 { 464 // see if we had this 465 PPRIMEDATA pData = (PPRIMEDATA)pUser; 466 PLISTNODE pNode; 467 PPRIMEENTRY pEntry; 468 for (pNode = lstQueryFirstNode(&pData->llPrimes); 469 pNode; 470 pNode = pNode->pNext) 471 { 472 pEntry = (PPRIMEENTRY)pNode->pItemData; 473 if (pEntry->iPrime == n) 474 { 475 if (p < pEntry->iLowestPowerFound) 476 { 477 pEntry->iLowestPowerFound = p; 478 // printf(" %d^%d", n, p); 479 } 480 pEntry->iLastInt = pData->iCurrentInt; 481 482 // and stop 483 return 0; 484 } 485 } 486 487 exit(1); 488 489 return (0); 490 } */ 491 492 /* int mathGCDMulti(int *paNs, // in: array of integers 493 int cNs) // in: array item count (NOT array size) 494 { 495 int i; 496 double dGCD; 497 498 PLISTNODE pNode; 499 PPRIMEENTRY pEntry; 500 501 PRIMEDATA Data; 502 lstInit(&Data.llPrimes, TRUE); 503 504 // this is done by prime-factoring each frequency 505 // and then multiplying all primes with the lowest 506 // common power that we found: 507 508 // Example 1: If we have two timers with freq. 509 // 1000 and 1500, obviously, the master timer 510 // should run at 500 ms. 511 512 // With prime factorization, we end up like this: 513 514 // 1000 = 2^3 * 5^3 515 // 1500 = 2^2 * 3^1 * 5^3 516 517 // so the highest power for factor 2 is 2; 518 // the highest power for factor 3 is 0; 519 // the highest power for factor 5 is 3; 520 521 // freq = 2^2 * 5^3 = 500 522 523 // Example 2: If we have three timers with freq. 524 // 1000 and 1500 and 1800: 525 526 // 1000 = 2^3 * 5^3 527 // 1500 = 2^2 * 3^1 * 5^3 528 // 1800 = 2^3 * 3^2 * 5^2 529 530 // so the highest power for factor 2 is 2; 531 // the highest power for factor 3 is 0; 532 // the highest power for factor 5 is 2; 533 534 // freq = 2^2 * * 5^2 = 100 535 536 // Example 3: If we have four timers with freq. 537 // 1200 and 1500 and 1800 and 60: 538 539 // 1200 = 2^4 * 3^1 * 5^2 540 // 1500 = 2^2 * 3^1 * 5^3 541 // 1800 = 2^3 * 3^2 * 5^2 542 // 60 = 2^2 * 3^1 * 5^1 543 544 // so the highest power for factor 2 is 2; 545 // the highest power for factor 3 is 1; 546 // the highest power for factor 5 is 1; 547 548 // freq = 2^2 * 3^1 * 5^1 = 60 549 550 // go thru the ints array to create 551 // an entry for each prime there is 552 for (i = 0; 553 i < cNs; 554 i++) 555 { 556 // printf("\nFactoring %d\n", paNs[i]); 557 Data.iCurrentInt = paNs[i]; 558 mathFactorPrime(paNs[i], 559 GCDMultiCallbackCreate, 560 &Data); 561 } 562 563 // now run this a second time to find the 564 // lowest prime for each 565 for (i = 0; 566 i < cNs; 567 i++) 568 { 569 // printf("\nTouching %d\n", paNs[i]); 570 Data.iCurrentInt = paNs[i]; 571 mathFactorPrime(paNs[i], 572 GCDMultiCallbackLowest, 573 &Data); 574 575 // all list items that were just touched 576 // now have iLastInt set to the current 577 // integer; so go thru the list and set 578 // all items which do NOT have that set 579 // to power 0 because we must not use them 580 // in factoring 581 for (pNode = lstQueryFirstNode(&Data.llPrimes); 582 pNode; 583 pNode = pNode->pNext) 584 { 585 pEntry = (PPRIMEENTRY)pNode->pItemData; 586 if (pEntry->iLastInt != paNs[i]) 587 { 588 pEntry->iLowestPowerFound = 0; 589 // printf(" ###%d^%d", pEntry->iPrime, 0); 590 } 591 } 592 } 593 594 // printf("\nNew:\n"); 595 596 // now compose the GCD 597 dGCD = 1; 598 for (pNode = lstQueryFirstNode(&Data.llPrimes); 599 pNode; 600 pNode = pNode->pNext) 601 { 602 pEntry = (PPRIMEENTRY)pNode->pItemData; 603 604 // printf(" %d^%d", pEntry->iPrime, pEntry->iLowestPowerFound); 605 606 if (pEntry->iLowestPowerFound) 607 dGCD *= pow(pEntry->iPrime, pEntry->iLowestPowerFound); 608 } 609 610 lstClear(&Data.llPrimes); 611 612 return dGCD; 613 } */ 614 615 // testcase 616 617 #ifdef BUILD_MAIN 618 619 #define INCL_DOSMISC 620 #include <os2.h> 621 622 int callback(int n, 623 int p, 624 void *pUser) 625 { 626 if (p > 1) 627 printf("%d^%d ", n, p); 628 else 629 printf("%d ", n); 630 fflush(stdout); 631 632 return (0); 633 } 634 635 int main (int argc, char *argv[]) 636 { 637 if (argc > 1) 638 { 639 int i, 640 c, 641 cInts = argc - 1; 642 ULONG ulms, ulms2; 643 int *aInts = malloc(sizeof(int) * cInts); 644 645 for (c = 0; 646 c < cInts; 647 c++) 648 { 649 aInts[c] = atoi(argv[c + 1]); 650 } 651 652 DosQuerySysInfo(QSV_MS_COUNT, 653 QSV_MS_COUNT, 654 &ulms, 655 sizeof(ulms)); 656 657 c = mathGCDMulti(aInts, 658 cInts); 659 660 DosQuerySysInfo(QSV_MS_COUNT, 661 QSV_MS_COUNT, 662 &ulms2, 663 sizeof(ulms2)); 664 665 printf("\nGCD is %d, %d ms time.\n", 666 c, 667 ulms2 - ulms); 668 669 for (i = 0; 670 i < cInts; 671 i++) 672 { 673 printf(" %d / %d = %d rem. %d\n", 674 aInts[i], c, aInts[i] / c, aInts[i] % c); 675 } 676 677 /* c = mathFactorBrute(atoi(argv[1]), 678 callback, 679 0); 680 printf("\n%d factors found.\n", c); */ 681 } 682 683 return (0); 684 } 685 686 #endif 358
Note:
See TracChangeset
for help on using the changeset viewer.