Loading lang_c_06_alloc...
#ifndef PRIMES_H #define PRIMES_H
#include <stdbool.h>
bool // tested is a prime number isPrime(const int *primes, int primeCount, int tested);
#endif // PRIMES_H
#include "primes.h"
bool // tested is a prime number isPrime(const int *primes, int primeCount, int tested) { if(tested==2) { return true; // 2 is a prime numer } if((tested<2)||(tested%2==0)) { return false; // 0, 1 and even numbers are not prime numbers } for(int i=0; i<primeCount; ++i) { int div=primes[i]; if(div*div>tested) // no need to search further and not { return true; // multiple of anything so far, thus prime number } if(tested%div==0) // multiple of a previous prime number, { return false; // thus not a prime number } } int lastDiv=primeCount>1 ? primes[primeCount-1] : 3; for(int div=lastDiv; div*div<=tested; div+=2) // go on with odd numbers { if(tested%div==0) // multiple of an odd number { return false; // thus not a prime number } } return true; // not multiple of anything so far, thus prime number }
#include <stdio.h> #include "primes.h"
void test_isPrime(void) { printf("\n~~~~ %s() ~~~~\n", __func__); int primes[]={2, 3, 5, 7, 11, 13, 17, 19}; int primeCount=(int)(sizeof(primes)/sizeof(primes[0])); for(int i=0; i<100; ++i) { if(isPrime(primes, primeCount, i)) { printf("%d ", i); } } printf("\n"); }
int main(void) { test_isPrime(); return 0; }
static // only for internal use in this module int // next prime number (after last of primes) nextPrime(const int *primes, int primeCount) { if(primeCount<2) { return primeCount+2; // start with 2 and 3 } int tested=primes[primeCount-1]; do { tested+=2; // go on with odd numbers } while(!isPrime(primes, primeCount, tested)); return tested; }
void populatePrimes(int *primes, int primeCount) { for(int i=0; i<primeCount; ++i) { primes[i]=nextPrime(primes, i); } }
void displayPrimes(const int *primes, int primeCount, int limit) { if(limit>0) { for(int i=0; i<limit; ++i) { printf("%d%c", primes[i], (i%10)==9 ? '\n' : '\t'); } if(primeCount>limit) { printf("...\n"); } else if(limit%10) { printf("\n"); } } printf("last of %d primes: %d\n", primeCount, primeCount ? primes[primeCount-1] : 0); }
void test_populatePrimes(void) { printf("\n~~~~ %s() ~~~~\n", __func__); int primes[1000]; int primeCount=(int)(sizeof(primes)/sizeof(primes[0])); populatePrimes(primes, primeCount); displayPrimes(primes, primeCount, 100); }
... int *primes=(int *)malloc(primeCount*sizeof(int)); ...
<stdlib.h>comme précisé dans la documentation.
... free(primes); ...
... int *primes=(int *)malloc(primeCount*sizeof(int)); if(primes==NULL) { abort(); } ...
int * // allocated prime numbers allocatePrimes(int primeCount) { int *primes=(int *)malloc(primeCount*sizeof(int)); if(primes==NULL) { abort(); } populatePrimes(primes, primeCount); return primes; }
void extendPrimes(int **inout_primes, int *inout_primeCount, int nextPrimeCount) { //-- load inout-parameters -- int *primes=*inout_primes; int primeCount=*inout_primeCount; //-- obtain new storage -- int *tmp=(int *)malloc(nextPrimeCount*sizeof(int)); if(tmp==NULL) { abort(); } //-- duplicate previous prime numbers -- int limit=primeCount<nextPrimeCount ? primeCount : nextPrimeCount; for(int i=0; i<limit; ++i) { tmp[i]=primes[i]; } //-- give back previous storage and substitute with the new one -- free(primes); primes=tmp; //-- compute new prime numbers -- for(int i=primeCount; i<nextPrimeCount; ++i) { primes[i]=nextPrime(primes, i); } //-- store out-parameters -- *inout_primes=primes; *inout_primeCount=nextPrimeCount; }
void test_extendPrimes(int extentStep, int extentCount) { printf("\n~~~~ %s(%d, %d) ~~~~\n", __func__, extentStep, extentCount); int primeCount=0; int *primes=NULL; for(int i=0; i<extentCount; ++i) { extendPrimes(&primes, &primeCount, (i+1)*extentStep); displayPrimes(primes, primeCount, 10); } free(primes); }
<string.h>, remplacez la boucle de recopie de la fonction extendPrimes() par une invocation de memcpy().
{ ... memcpy(tmp, primes, limit*sizeof(int)); ... }
{ ... //-- extend storage -- primes=(int *)realloc(primes, nextPrimeCount*sizeof(int)); if(primes==NULL) { abort(); } ... }
void allocatePrimesUntil(int **out_primes, int *out_primeCount, int lastTested) { int *primes=NULL; int primeCount=0; for(int capacity=primeCount; ; ++primeCount) { int prime=nextPrime(primes, primeCount); if(prime>lastTested) { break; } if(primeCount==capacity) // no space left { //-- determine new capacity -- int minChunk=32, maxChunk=1024*1024; if(capacity<minChunk) { capacity=minChunk; } else if(capacity<maxChunk) { capacity*=2; } else { capacity+=maxChunk; } //-- extend storage -- primes=(int *)realloc(primes, capacity*sizeof(int)); if(primes==NULL) { abort(); } } primes[primeCount]=prime; } //-- store out-parameters -- *out_primes=primes; *out_primeCount=primeCount; }
void test_allocatePrimesUntil(int lastTested) { printf("\n~~~~ %s(%d) ~~~~\n", __func__, lastTested); int primeCount; int *primes=NULL; allocatePrimesUntil(&primes, &primeCount, lastTested); displayPrimes(primes, primeCount, 100); free(primes); }
void allocatePrimesUntil(int **out_primes, int *out_primeCount, int lastTested) { int *primes=NULL; int primeCount=0; extendPrimesUntil(&primes, &primeCount, lastTested); //-- store out-parameters -- *out_primes=primes; *out_primeCount=primeCount; }
//----------------------------------------------------------------------------
#ifndef PRIMES_H #define PRIMES_H
#include <stdbool.h>
bool // tested is a prime number isPrime(const int *primes, int primeCount, int tested);
void populatePrimes(int *primes, int primeCount);
int * // allocated prime numbers allocatePrimes(int primeCount);
void extendPrimes(int **inout_primes, int *inout_primeCount, int nextPrimeCount);
void allocatePrimesUntil(int **out_primes, int *out_primeCount, int lastTested);
void extendPrimesUntil(int **inout_primes, int *inout_primeCount, int lastTested);
#endif // PRIMES_H
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "primes.h" #include <stdlib.h> #include <string.h>
#define USE_REALLOC 1 #define USE_MEMCPY 1
bool // tested is a prime number isPrime(const int *primes, int primeCount, int tested) { if(tested==2) { return true; // 2 is a prime numer } if((tested<2)||(tested%2==0)) { return false; // 0, 1 and even numbers are not prime numbers } for(int i=0; i<primeCount; ++i) { int div=primes[i]; if(div*div>tested) // no need to search further and not { return true; // multiple of anything so far, thus prime number } if(tested%div==0) // multiple of a previous prime number, { return false; // thus not a prime number } } int lastDiv=primeCount>1 ? primes[primeCount-1] : 3; for(int div=lastDiv; div*div<=tested; div+=2) // go on with odd numbers { if(tested%div==0) // multiple of an odd number { return false; // thus not a prime number } } return true; // not multiple of anything so far, thus prime number }
static // only for internal use in this module int // next prime number (after last of primes) nextPrime(const int *primes, int primeCount) { if(primeCount<2) { return primeCount+2; // start with 2 and 3 } int tested=primes[primeCount-1]; do { tested+=2; // go on with odd numbers } while(!isPrime(primes, primeCount, tested)); return tested; }
void populatePrimes(int *primes, int primeCount) { for(int i=0; i<primeCount; ++i) { primes[i]=nextPrime(primes, i); } }
int * // allocated prime numbers allocatePrimes(int primeCount) { int *primes=(int *)malloc(primeCount*sizeof(int)); if(primes==NULL) { abort(); } populatePrimes(primes, primeCount); return primes; }
void extendPrimes(int **inout_primes, int *inout_primeCount, int nextPrimeCount) { //-- load inout-parameters -- int *primes=*inout_primes; int primeCount=*inout_primeCount; #if USE_REALLOC //-- extend storage -- primes=(int *)realloc(primes, nextPrimeCount*sizeof(int)); if(primes==NULL) { abort(); } #else //-- obtain new storage -- int *tmp=(int *)malloc(nextPrimeCount*sizeof(int)); if(tmp==NULL) { abort(); } //-- duplicate previous prime numbers -- int limit=primeCount<nextPrimeCount ? primeCount : nextPrimeCount; # if USE_MEMCPY memcpy(tmp, primes, limit*sizeof(int)); # else for(int i=0; i<limit; ++i) { tmp[i]=primes[i]; } # endif //-- give back previous storage and substitute with the new one -- free(primes); primes=tmp; #endif //-- compute new prime numbers -- for(int i=primeCount; i<nextPrimeCount; ++i) { primes[i]=nextPrime(primes, i); } //-- store out-parameters -- *inout_primes=primes; *inout_primeCount=nextPrimeCount; }
void allocatePrimesUntil(int **out_primes, int *out_primeCount, int lastTested) { int *primes=NULL; int primeCount=0; #if 0 // first version for(int capacity=primeCount; ; ++primeCount) { int prime=nextPrime(primes, primeCount); if(prime>lastTested) { break; } if(primeCount==capacity) // no space left { //-- determine new capacity -- int minChunk=32, maxChunk=1024*1024; if(capacity<minChunk) { capacity=minChunk; } else if(capacity<maxChunk) { capacity*=2; } else { capacity+=maxChunk; } //-- extend storage -- primes=(int *)realloc(primes, capacity*sizeof(int)); if(primes==NULL) { abort(); } } primes[primeCount]=prime; } #else // second version extendPrimesUntil(&primes, &primeCount, lastTested); #endif //-- store out-parameters -- *out_primes=primes; *out_primeCount=primeCount; }
void extendPrimesUntil(int **inout_primes, int *inout_primeCount, int lastTested) { //-- load inout-parameters -- int *primes=*inout_primes; int primeCount=*inout_primeCount; //-- perform work -- for(int capacity=primeCount; ;++primeCount) { int prime=nextPrime(primes, primeCount); if(prime>lastTested) { break; } if(primeCount==capacity) // no space left { //-- determine new capacity -- int minChunk=32, maxChunk=1024*1024; if(capacity<minChunk) { capacity=minChunk; } else if(capacity<maxChunk) { capacity*=2; } else { capacity+=maxChunk; } //-- extend storage -- primes=(int *)realloc(primes, capacity*sizeof(int)); if(primes==NULL) { abort(); } } primes[primeCount]=prime; } //-- store out-parameters -- *inout_primes=primes; *inout_primeCount=primeCount; }
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <stdio.h> #include <stdlib.h> #include "primes.h"
void displayPrimes(const int *primes, int primeCount, int limit) { if(limit>0) { for(int i=0; i<limit; ++i) { printf("%d%c", primes[i], (i%10)==9 ? '\n' : '\t'); } if(primeCount>limit) { printf("...\n"); } else if(limit%10) { printf("\n"); } } printf("last of %d primes: %d\n", primeCount, primeCount ? primes[primeCount-1] : 0); }
void test_isPrime(void) { printf("\n~~~~ %s() ~~~~\n", __func__); int primes[]={2, 3, 5, 7, 11, 13, 17, 19}; int primeCount=(int)(sizeof(primes)/sizeof(primes[0])); for(int i=0; i<100; ++i) { if(isPrime(primes, primeCount, i)) { printf("%d ", i); } } printf("\n"); }
void test_populatePrimes(void) { printf("\n~~~~ %s() ~~~~\n", __func__); int primes[1000]; int primeCount=(int)(sizeof(primes)/sizeof(primes[0])); populatePrimes(primes, primeCount); displayPrimes(primes, primeCount, 100); }
void test_allocatePrimes(int primeCount) { printf("\n~~~~ %s(%d) ~~~~\n", __func__, primeCount); #if 0 // first version int *primes=(int *)malloc(primeCount*sizeof(int)); populatePrimes(primes, primeCount); #else // second version int *primes=allocatePrimes(primeCount); #endif displayPrimes(primes, primeCount, 100); free(primes); }
void test_extendPrimes(int extentStep, int extentCount) { printf("\n~~~~ %s(%d, %d) ~~~~\n", __func__, extentStep, extentCount); int primeCount=0; int *primes=NULL; for(int i=0; i<extentCount; ++i) { extendPrimes(&primes, &primeCount, (i+1)*extentStep); displayPrimes(primes, primeCount, 10); } free(primes); }
void test_allocatePrimesUntil(int lastTested) { printf("\n~~~~ %s(%d) ~~~~\n", __func__, lastTested); int primeCount; int *primes=NULL; allocatePrimesUntil(&primes, &primeCount, lastTested); displayPrimes(primes, primeCount, 100); free(primes); }
void test_extendPrimesUntil(int extentStep, int extentCount) { printf("\n~~~~ %s(%d, %d) ~~~~\n", __func__, extentStep, extentCount); int primeCount=0; int *primes=NULL; for(int i=0; i<extentCount; ++i) { extendPrimesUntil(&primes, &primeCount, (i+1)*extentStep); displayPrimes(primes, primeCount, 10); } free(primes); }
int main(void) { test_isPrime(); test_populatePrimes(); test_allocatePrimes(1000); test_extendPrimes(100000, 10); test_allocatePrimesUntil(1000000); test_extendPrimesUntil(1000000, 10); return 0; }
//----------------------------------------------------------------------------