Skip to content

Latest commit

 

History

History
357 lines (268 loc) · 9.56 KB

C_Examples.md

File metadata and controls

357 lines (268 loc) · 9.56 KB

libprimesieve C examples

This is a short selection of C code snippets that use libprimesieve to generate prime numbers. These examples cover the most frequently used functionality of libprimesieve. Arguably the most useful feature provided by libprimesieve is the primesieve_iterator which lets you iterate over primes using the primesieve_next_prime() or primesieve_prev_prime() functions.

Additional libprimesieve documentation links:

primesieve_next_prime()

By default primesieve_next_prime() generates primes > 0 i.e. 2, 3, 5, 7, ...

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  primesieve_iterator it;
  primesieve_init(&it);

  uint64_t sum = 0;
  uint64_t prime = 0;

  /* iterate over the primes < 10^9 */
  while ((prime = primesieve_next_prime(&it)) < 1000000000)
    sum += prime;

  printf("Sum of the primes below 10^9 = %" PRIu64 "\n", sum);
  primesieve_free_iterator(&it);

  return 0;
}

primesieve_skipto()

This method changes the start number of the primesieve_iterator object. (By default the start number is initialized to 0). The stop_hint parameter is used for performance optimization, primesieve_iterator only buffers primes up to this limit.

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  primesieve_iterator it;
  primesieve_init(&it);

  /* primesieve_skipto(&it, start, stop_hint) */
  primesieve_skipto(&it, 1000, 1100);
  uint64_t prime;

  /* iterate over primes from ]1000, 1100] */
  while ((prime = primesieve_next_prime(&it)) <= 1100)
    printf("%" PRIu64 "\n", prime);

  primesieve_free_iterator(&it);
  return 0;
}

primesieve_prev_prime()

Before using primesieve_prev_prime() you must first change the start number using the primesieve_skipto() function as the start number is initialized to 0 be default.

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  primesieve_iterator it;
  primesieve_init(&it);

  /* primesieve_skipto(&it, start, stop_hint) */
  primesieve_skipto(&it, 2000, 1000);
  uint64_t prime;

  /* iterate over primes from ]2000, 1000] */
  while ((prime = primesieve_prev_prime(&it)) >= 1000)
    printf("%" PRIu64 "\n", prime);

  primesieve_free_iterator(&it);
  return 0;
}

primesieve_generate_primes()

Stores the primes inside [start, stop] in an array. The last primes type parameter may be one of: SHORT_PRIMES, USHORT_PRIMES, INT_PRIMES, UINT_PRIMES, LONG_PRIMES, ULONG_PRIMES, LONGLONG_PRIMES, ULONGLONG_PRIMES, INT16_PRIMES, UINT16_PRIMES, INT32_PRIMES, UINT32_PRIMES, INT64_PRIMES, UINT64_PRIMES.

#include <primesieve.h>
#include <stdio.h>

int main()
{
  uint64_t start = 0;
  uint64_t stop = 1000;
  size_t size;

  /* Get an array with the primes inside [start, stop] */
  int* primes = (int*) primesieve_generate_primes(start, stop, &size, INT_PRIMES);

  for (size_t i = 0; i < size; i++)
    printf("%i\n", primes[i]);

  primesieve_free(primes);
  return 0;
}

primesieve_generate_n_primes()

Stores the first n primes ≥ start in an array. The last primes type parameter may be one of: SHORT_PRIMES, USHORT_PRIMES, INT_PRIMES, UINT_PRIMES, LONG_PRIMES, ULONG_PRIMES, LONGLONG_PRIMES, ULONGLONG_PRIMES, INT16_PRIMES, UINT16_PRIMES, INT32_PRIMES, UINT32_PRIMES, INT64_PRIMES, UINT64_PRIMES.

#include <primesieve.h>
#include <stdio.h>

int main()
{
  uint64_t n = 1000;
  uint64_t start = 0;

  /* Get an array with the first 1000 primes */
  int64_t* primes = (int64_t*) primesieve_generate_n_primes(n, start, INT64_PRIMES);

  for (size_t i = 0; i < n; i++)
    printf("%li\n", primes[i]);

  primesieve_free(primes);
  return 0;
}

primesieve_count_primes()

Counts the primes inside [start, stop]. This method is multi-threaded and uses all available CPU cores by default.

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  /* primesieve_count_primes(start, stop) */
  uint64_t count = primesieve_count_primes(0, 1000);
  printf("Primes below 1000 = %" PRIu64 "\n", count);

  return 0;
}

primesieve_nth_prime()

This method finds the nth prime e.g. nth_prime(25) = 97. This method is multi-threaded and uses all available CPU cores by default.

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  /* primesieve_nth_prime(n, start) */
  uint64_t n = 25;
  uint64_t prime = primesieve_nth_prime(n, 0);
  printf("%" PRIu64 "th prime = %" PRIu64 "\n", n, prime);

  return 0;
}

Error handling

If an error occurs, libprimesieve functions with a uint64_t return type return PRIMESIEVE_ERROR (which is defined as UINT64_MAX in <primesieve.h>) and the corresponding error message is printed to the standard error stream.

#include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t count = primesieve_count_primes(0, 1000);

  if (count != PRIMESIEVE_ERROR)
    printf("Primes below 1000 = %" PRIu64 "\n", count);
  else
    printf("Error in libprimesieve!\n");

  return 0;
}

libprimesieve also sets the C errno variable to EDOM if an error occurs. This makes it possible to check if an error has occurred in libprimesieve functions with a void return type. errno is also useful for checking after a computation that no error has occurred, this way you don't have to check the return value of every single primesieve function call.

#include <primesieve.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>

int main()
{
  /* Reset errno before computation */
  errno = 0;

  primesieve_iterator it;
  primesieve_init(&it);
  uint64_t sum = 0;
  uint64_t prime = 0;

  while ((prime = primesieve_next_prime(&it)) < 1000000000)
    sum += prime;

  /* Check errno after computation */
  if (errno != EDOM)
    printf("Sum of the primes below 10^9 = %" PRIu64 "\n", sum);
  else
    printf("Error in libprimesieve!\n");

  primesieve_free_iterator(&it);
  return 0;
}

How to compile

Unix-like OSes

If libprimesieve is installed on your system, then you can compile any of the C example programs above using:

cc -O3 primes.c -o primes -lprimesieve

If you have built libprimesieve yourself, then the default installation path is usually /usr/local/lib. Running the ldconfig program after make install ensures that Linux's dynamic linker/loader will find the shared primesieve library when you execute your program. However, some OSes are missing the ldconfig program or ldconfig does not include /usr/local/lib by default. In these cases you need to export some environment variables:

export LIBRARY_PATH=/usr/local/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=/usr/local/include:$C_INCLUDE_PATH

Microsoft Visual C++

cl /O2 /EHsc /MD primes.c /I "path\to\primesieve\include" /link "path\to\primesieve.lib"

CMake support

If you are using the CMake build system to compile your program and libprimesieve is installed on your system, then you can add the following two lines to your CMakeLists.txt to link your program against libprimesieve.

find_package(primesieve REQUIRED)
target_link_libraries(your_program primesieve::primesieve)

To link against the static libprimesieve use:

find_package(primesieve REQUIRED static)
target_link_libraries(your_program primesieve::primesieve)

Minimal CMake project file

If you want to build your C program (named primes.c) using CMake, then you can use the minimal CMakeLists.txt below. Note that this requires that libprimesieve is installed on your system. Using CMake has the advantage that you don't need to specify the libprimesieve include path and the -lprimesieve linker option when building your project.

# File: CMakeLists.txt
cmake_minimum_required(VERSION 3.4...3.19)
project(primes C CXX)
find_package(primesieve REQUIRED)
add_executable(primes primes.c)
target_link_libraries(primes primesieve::primesieve)

Put the CMakeLists.txt file from above into the same directory as your primes.c file.
Then open a terminal, cd into that directory and build your project using:

cmake . -DCMAKE_BUILD_TYPE=Release
cmake --build .

Using the MSVC compiler (Windows) the build instructions are slightly different. First you should link against the static libprimesieve in your CMakeLists.txt using: find_package(primesieve REQUIRED static). Next open a Visual Studio Command Prompt, cd into your project's directory and build your project using:

cmake -G "Visual Studio 16 2019" .
cmake --build . --config Release