Ignore:
Timestamp:
Jun 14, 2002, 2:20:11 PM (23 years ago)
Author:
umoeller
Message:

Misc updates.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/math.c

    r88 r174  
    6767
    6868}
    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 that
    74              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 efficiently
    76    implemented as shift-left 1 and shift-right 1 resp.
    77 
    78     Found at http://remus.rutgers.edu/~rhoads/Code/int_gcd.c
    79 */
    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); */
    10669
    10770/*
     
    393356}
    394357
    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.