Chapter 33. Non-graph related functions

1. igraph version number
2. Running mean of a time series
3. Random sampling from very long sequences
4. Random sampling of spatial points
5. Convex hull of a set of points on a plane
6. Fitting power-law distributions to empirical data

1. igraph version number

1.1. igraph_version — Return the version of the igraph C library

int igraph_version(const char **version_string,
                   int *major,
                   int *minor,
                   int *subminor);

Arguments: 

version_string:

Pointer to a string pointer. If not null, it is set to the igraph version string, e.g. "0.6" or "0.5.3". This string should not be modified or deallocated.

major:

If not a null pointer, then it is set to the major igraph version. E.g. for version "0.5.3" this is 0.

minor:

If not a null pointer, then it is set to the minor igraph version. E.g. for version "0.5.3" this is 5.

subminor:

If not a null pointer, then it is set to the subminor igraph version. E.g. for version "0.5.3" this is 3.

Returns: 

Error code.

Time complexity: O(1).

Example 33.1.  File examples/simple/igraph_version.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2010-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard st, Cambridge MA, 02139 USA

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <string.h>

int main() {

    char tmp[100];
    const char *string;
    int major, minor, subminor;

    igraph_version(&string, &major, &minor, &subminor);
    sprintf(tmp, "%i.%i.%i", major, minor, subminor);

    if (strncmp(string, tmp, strlen(tmp))) {
        return 1;
    }

    return 0;
}


2. Running mean of a time series

2.1. igraph_running_mean — Calculates the running mean of a vector.

int igraph_running_mean(const igraph_vector_t *data, igraph_vector_t *res,
                        igraph_integer_t binwidth);

The running mean is defined by the mean of the previous binwidth values.

Arguments: 

data:

The vector containing the data.

res:

The vector containing the result. This should be initialized before calling this function and will be resized.

binwidth:

Integer giving the width of the bin for the running mean calculation.

Returns: 

Error code.

Time complexity: O(n), n is the length of the data vector.

3. Random sampling from very long sequences

3.1. igraph_random_sample — Generates an increasing random sequence of integers.

int igraph_random_sample(igraph_vector_t *res, igraph_real_t l, igraph_real_t h,
                         igraph_integer_t length);

This function generates an increasing sequence of random integer numbers from a given interval. The algorithm is taken literally from (Vitter 1987). This method can be used for generating numbers from a very large interval. It is primarily created for randomly selecting some edges from the sometimes huge set of possible edges in a large graph.

Note that the type of the lower and the upper limit is igraph_real_t, not igraph_integer_t. This does not mean that you can pass fractional numbers there; these values must still be integral, but we need the longer range of igraph_real_t in several places in the library (for instance, when generating Erdos-Renyi graphs).

Arguments: 

res:

Pointer to an initialized vector. This will hold the result. It will be resized to the proper size.

l:

The lower limit of the generation interval (inclusive). This must be less than or equal to the upper limit, and it must be integral. Passing a fractional number here results in undefined behaviour.

h:

The upper limit of the generation interval (inclusive). This must be greater than or equal to the lower limit, and it must be integral. Passing a fractional number here results in undefined behaviour.

length:

The number of random integers to generate.

Returns: 

The error code IGRAPH_EINVAL is returned in each of the following cases: (1) The given lower limit is greater than the given upper limit, i.e. l > h. (2) Assuming that l < h and N is the sample size, the above error code is returned if N > |h - l|, i.e. the sample size exceeds the size of the candidate pool.

Time complexity: according to (Vitter 1987), the expected running time is O(length).

Reference:

(Vitter 1987)

J. S. Vitter. An efficient algorithm for sequential random sampling. ACM Transactions on Mathematical Software, 13(1):58--67, 1987.

Example 33.2.  File examples/simple/igraph_random_sample.c

/* -*- mode: C -*-  */
/*
  Test suite for random sampling.
  Copyright (C) 2011 Minh Van Nguyen <nguyenminh2@gmail.com>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301 USA
*/

#include <igraph.h>
#include <math.h>
#include <stdio.h>

#define R_INTEGER(a,b) (igraph_rng_get_integer(igraph_rng_default(), (a), (b)))

/* test parameters */
typedef struct {
    igraph_integer_t low;
    igraph_integer_t high;
    igraph_integer_t length;
    int retval;
} sampling_test_t;

/* Error tests. Don't be afraid to crash the library function.
 */
int error_test() {
    igraph_vector_t V;
    int i, n, ret;
    sampling_test_t *test;

    igraph_rng_seed(igraph_rng_default(), 42); /* make tests deterministic */
    igraph_vector_init(&V, /*size*/ 0);

    /* test parameters */
    /*----------low----high----length----retval----------*/
    /* lower limit is greater than upper limit */
    sampling_test_t lower_bigger = {300, 200, 10, IGRAPH_EINVAL};
    /* sample size is greater than size of candidate pool */
    sampling_test_t sample_size_bigger = {200, 300, 500, IGRAPH_EINVAL};

    sampling_test_t *all_checks[] = {/* 1 */ &lower_bigger,
                                     /* 2 */ &sample_size_bigger};

    /* failure is the mother of success */
    igraph_set_error_handler(igraph_error_handler_ignore);
    n = 2;
    for (i = 0; i < n; i++) {
        test = all_checks[i];
        ret = igraph_random_sample(&V, test->low, test->high, test->length);
        if (ret != test->retval) {
            printf("Error test no. %d failed.\n", (int)(i + 1));
            return IGRAPH_FAILURE;
        }
    }
    igraph_set_error_handler(igraph_error_handler_abort);

    igraph_vector_destroy(&V);

    return IGRAPH_SUCCESS;
}

/* Get a few random samples and test their properties.
 */
int random_sample_test() {
    const igraph_integer_t min = -1000;
    const igraph_integer_t max = 1000;
    igraph_integer_t low;       /* lower limit */
    igraph_integer_t high;      /* upper limit */
    igraph_integer_t length;    /* sample size */
    igraph_integer_t poolsize;  /* size of candidate pool */
    igraph_real_t sP;           /* population total sum */
    igraph_real_t ss;           /* sample total sum */
    igraph_vector_t V;
    int i;

    igraph_rng_seed(igraph_rng_default(), 57); /* make tests deterministic */

    /* The generated sequence of numbers must be in increasing order. */
    igraph_vector_init(&V, /*size*/ 0);
    do {
        high = (igraph_integer_t)R_INTEGER(min, max);
    } while (high == min);
    do {
        low = (igraph_integer_t)R_INTEGER(min, max);
    } while (low >= high);
    poolsize = (igraph_integer_t)fabs((double)high - (double)low);
    do {
        length = (igraph_integer_t)R_INTEGER(1, max);
    } while (length > poolsize);
    igraph_random_sample(&V, low, high, length);
    if (length != igraph_vector_size(&V)) {
        printf("Requested vector length and resulting length mismatch.\n");
        return IGRAPH_FAILURE;
    }
    for (i = 0; i < length - 1; i++) {
        if (VECTOR(V)[i] >= VECTOR(V)[i + 1]) {
            printf("Sample not in increasing order.\n");
            return IGRAPH_FAILURE;
        }
    }
    igraph_vector_destroy(&V);

    /* Let P be a candidate pool of positive integers with total sum s_P. */
    /* Let S be a random sample from P and having total sum s_S. Then we */
    /* have the bound s_s <= s_P. */
    igraph_vector_init(&V, /*size*/ 0);
    low = 1;
    do {
        high = (igraph_integer_t)R_INTEGER(low, max);
    } while (high == low);
    poolsize = (igraph_integer_t)fabs((double)high - (double)low);
    do {
        length = (igraph_integer_t)R_INTEGER(low, max);
    } while (length > poolsize);
    igraph_random_sample(&V, low, high, length);
    /* Use Gauss' formula to sum all consecutive positive integers from 1 */
    /* up to and including an upper limit. In LaTeX, Gauss' formula is */
    /* \sum_{i=1}^n i = \frac{n(n+1)}{2} where n is the upper limit. */
    sP = (high * (high + 1)) / 2;
    ss = igraph_vector_sum(&V);
    if (ss > sP) {
        printf("Sum of sampled sequence exceeds sum of whole population.\n");
        return IGRAPH_FAILURE;
    }
    igraph_vector_destroy(&V);

    return IGRAPH_SUCCESS;
}

int equal_test() {
    igraph_vector_t V;
    int i;

    igraph_vector_init(&V, 0);

    igraph_random_sample(&V, 0, 0, 1);
    if (igraph_vector_size(&V) != 1) {
        return 1;
    }
    if (VECTOR(V)[0] != 0) {
        return 2;
    }

    igraph_random_sample(&V, 10, 10, 1);
    if (igraph_vector_size(&V) != 1) {
        return 3;
    }
    if (VECTOR(V)[0] != 10) {
        return 4;
    }

    igraph_random_sample(&V, 2, 12, 11);
    if (igraph_vector_size(&V) != 11) {
        return 5;
    }
    for (i = 0; i < 11; i++)
        if (VECTOR(V)[i] != i + 2) {
            return 6;
        }

    igraph_vector_destroy(&V);
    return 0;
}

int rare_test() {
    igraph_vector_t V;

    igraph_vector_init(&V, 0);

    igraph_random_sample(&V, 0, 0, 1);
    if (igraph_vector_size(&V) != 1) {
        return 1;
    }
    if (VECTOR(V)[0] != 0) {
        return 2;
    }

    igraph_random_sample(&V, 10, 10, 1);
    if (igraph_vector_size(&V) != 1) {
        return 3;
    }
    if (VECTOR(V)[0] != 10) {
        return 4;
    }

    igraph_vector_destroy(&V);
    return 0;
}

int main() {
    int ret;

    ret = error_test();
    if (ret) {
        return 1;
    }
    ret = random_sample_test();
    if (ret) {
        return 2;
    }
    ret = equal_test();
    if (ret) {
        return 3;
    }
    ret = rare_test();
    if (ret) {
        return 4;
    }

    return 0;
}


4. Random sampling of spatial points

4.1. igraph_sample_sphere_surface — Sample points uniformly from the surface of a sphere

int igraph_sample_sphere_surface(igraph_integer_t dim, igraph_integer_t n,
                                 igraph_real_t radius,
                                 igraph_bool_t positive,
                                 igraph_matrix_t *res);

The center of the sphere is at the origin.

Arguments: 

dim:

The dimension of the random vectors.

n:

The number of vectors to sample.

radius:

Radius of the sphere, it must be positive.

positive:

Whether to restrict sampling to the positive orthant.

res:

Pointer to an initialized matrix, the result is stored here, each column will be a sampled vector. The matrix is resized, as needed.

Returns: 

Error code.

Time complexity: O(n*dim*g), where g is the time complexity of generating a standard normal random number.

See also: 

4.2. igraph_sample_sphere_volume — Sample points uniformly from the volume of a sphere

int igraph_sample_sphere_volume(igraph_integer_t dim, igraph_integer_t n,
                                igraph_real_t radius,
                                igraph_bool_t positive,
                                igraph_matrix_t *res);

The center of the sphere is at the origin.

Arguments: 

dim:

The dimension of the random vectors.

n:

The number of vectors to sample.

radius:

Radius of the sphere, it must be positive.

positive:

Whether to restrict sampling to the positive orthant.

res:

Pointer to an initialized matrix, the result is stored here, each column will be a sampled vector. The matrix is resized, as needed.

Returns: 

Error code.

Time complexity: O(n*dim*g), where g is the time complexity of generating a standard normal random number.

See also: 

4.3. igraph_sample_dirichlet — Sample points from a Dirichlet distribution

int igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha,
                            igraph_matrix_t *res);

Arguments: 

n:

The number of vectors to sample.

alpha:

The parameters of the Dirichlet distribution. They must be positive. The length of this vector gives the dimension of the generated samples.

res:

Pointer to an initialized matrix, the result is stored here, one sample in each column. It will be resized, as needed.

Returns: 

Error code.

Time complexity: O(n * dim * g), where dim is the dimension of the sample vectors, set by the length of alpha, and g is the time complexity of sampling from a Gamma distribution.

See also: 

igraph_sample_sphere_surface() and igraph_sample_sphere_volume() for other methods to sample latent vectors.

5. Convex hull of a set of points on a plane

5.1. igraph_convex_hull — Determines the convex hull of a given set of points in the 2D plane

int igraph_convex_hull(const igraph_matrix_t *data, igraph_vector_t *resverts,
                       igraph_matrix_t *rescoords);

The convex hull is determined by the Graham scan algorithm. See the following reference for details:

Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3: Finding the convex hull.

Arguments: 

data:

vector containing the coordinates. The length of the vector must be even, since it contains X-Y coordinate pairs.

resverts:

the vector containing the result, e.g. the vector of vertex indices used as the corners of the convex hull. Supply NULL here if you are only interested in the coordinates of the convex hull corners.

rescoords:

the matrix containing the coordinates of the selected corner vertices. Supply NULL here if you are only interested in the vertex indices.

Returns: 

Error code: IGRAPH_ENOMEM: not enough memory

Time complexity: O(n log(n)) where n is the number of vertices

Example 33.3.  File examples/simple/igraph_convex_hull.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>

int check_convex_hull(igraph_matrix_t* coords) {
    igraph_vector_t result;
    igraph_matrix_t resmat;
    long int i;

    /* Testing with index output mode */
    igraph_vector_init(&result, 1);
    if (igraph_convex_hull(coords, &result, 0)) {
        return 1;
    }

    for (i = 0; i < igraph_vector_size(&result); i++) {
        printf("%ld ", (long)VECTOR(result)[i]);
    }
    printf("\n");
    igraph_vector_destroy(&result);

    /* Testing with coordinate output mode */
    igraph_matrix_init(&resmat, 0, 0);
    if (igraph_convex_hull(coords, 0, &resmat)) {
        return 1;
    }

    for (i = 0; i < igraph_matrix_nrow(&resmat); i++) {
        printf("%.3f %.3f ", MATRIX(resmat, i, 0), MATRIX(resmat, i, 1));
    }
    printf("\n");

    igraph_matrix_destroy(&resmat);

    return 0;
}

int test_simple() {
    igraph_real_t coords_array[][2] = {
        {3, 2}, {5, 1}, {4, 4}, {6, 4}, {4, 3},
        {2, 5}, {1, 3}, {2, 4}, {6, 3}, {9, 2}
    };
    igraph_matrix_t coords;
    int i, result;

    printf("test_simple\n");

    igraph_matrix_init(&coords, 10, 2);
    for (i = 0; i < 20; i++) {
        MATRIX(coords, i / 2, i % 2) = coords_array[i / 2][i % 2];
    }
    result = check_convex_hull(&coords);
    igraph_matrix_destroy(&coords);
    return result;
}

int test_collinear() {
    igraph_real_t coords_array[][2] =
    {{3, 2}, {5, 1}, {7, 0}, {9, -1}, {11, -2}};
    igraph_matrix_t coords;
    int i, result;

    printf("test_collinear\n");

    igraph_matrix_init(&coords, 5, 2);
    for (i = 0; i < 10; i++) {
        MATRIX(coords, i / 2, i % 2) = coords_array[i / 2][i % 2];
    }
    result = check_convex_hull(&coords);
    igraph_matrix_destroy(&coords);
    return result;
}

int test_degenerate() {
    igraph_matrix_t coords;
    int result;

    printf("test_degenerate\n");

    igraph_matrix_init(&coords, 2, 2);
    MATRIX(coords, 0, 0) = 3;
    MATRIX(coords, 0, 1) = 2;
    MATRIX(coords, 1, 0) = 5;
    MATRIX(coords, 1, 1) = 1;
    result = check_convex_hull(&coords);

    igraph_matrix_resize(&coords, 1, 2);
    MATRIX(coords, 0, 0) = 3;
    MATRIX(coords, 0, 1) = 2;
    result = check_convex_hull(&coords);

    igraph_matrix_resize(&coords, 0, 2);
    result = check_convex_hull(&coords);

    igraph_matrix_destroy(&coords);
    return result;
}

int test_bug_805() {
    igraph_real_t coords_array[][2] = {
        {0, 0}, {1, 0}, {0.707, 0.707}, {0, 1}, {-0.707, 0.707}, {-1, 0},
        {-0.707, -0.707}, {0, -1}, {0.707, -0.707}, {2, 0}, {1.414, 1.414}, {0, 2},
        {-1.414, 1.414}, {-2, 0}, {-1.414, -1.414}, {0, -2}, {1.414, -1.414}, {3, 0},
        {2.121, 2.121}, {0, 3}, {-2.121, 2.121}, {-3, 0}, {-2.121, -2.121}, {0, -3},
        {2.121, -2.121}, {4, 0}, {2.828, 2.828}, {0, 4}, {-2.828, 2.828}, {-4, 0},
        {-2.828, -2.828}, {0, -4}, {2.828, -2.828}
    };
    igraph_matrix_t coords;
    int i, result;

    printf("test_bug_805\n");

    igraph_matrix_init(&coords, 33, 2);
    for (i = 0; i < 66; i++) {
        MATRIX(coords, i / 2, i % 2) = coords_array[i / 2][i % 2];
    }
    result = check_convex_hull(&coords);
    igraph_matrix_destroy(&coords);
    return result;
}

int test_bug_1115() {
    igraph_real_t coords_array[][2] = {
        {37, 52}, {49, 49}, {52, 64}, {20, 26}, {40, 30}, {21, 47}, {17, 63}, {31, 62},
        {52, 33}, {51, 21}, {42, 41}, {31, 32}, {5, 25}, {12, 42}, {36, 16}, {52, 41},
        {27, 23}, {17, 33}, {13, 13}, {57, 58}, {62, 42}, {42, 57}, {16, 57}, {8, 52},
        {7, 38}, {27, 68}, {30, 48}, {43, 67}, {58, 48}, {58, 27}, {37, 69}, {38, 46},
        {46, 10}, {61, 33}, {62, 63}, {63, 69}, {32, 22}, {45, 35}, {59, 15}, {5, 6},
        {10, 17}, {21, 10}, {5, 64}, {30, 15}, {39, 10}, {32, 39}, {25, 32}, {25, 55},
        {48, 28}, {56, 37}, {30, 40}
    };
    igraph_matrix_t coords;
    int i, result;

    printf("test_bug_1115\n");

    igraph_matrix_init(&coords, 51, 2);
    for (i = 0; i < 102; i++) {
        MATRIX(coords, i / 2, i % 2) = coords_array[i / 2][i % 2];
    }
    result = check_convex_hull(&coords);
    igraph_matrix_destroy(&coords);
    return result;
}

int main() {
    int result;

    result = test_simple();
    if (result != 0) {
        return result;
    }

    result = test_collinear();
    if (result != 0) {
        return result;
    }

    result = test_degenerate();
    if (result != 0) {
        return result;
    }

    result = test_bug_805();
    if (result != 0) {
        return result;
    }

    result = test_bug_1115();
    if (result != 0) {
        return result;
    }

    return 0;
}


6. Fitting power-law distributions to empirical data

6.1. igraph_plfit_result_t — Result of fitting a power-law distribution to a vector

typedef struct igraph_plfit_result_t {
    igraph_bool_t continuous;
    double alpha;
    double xmin;
    double L;
    double D;
    double p;
} igraph_plfit_result_t;

This data structure contains the result of igraph_power_law_fit(), which tries to fit a power-law distribution to a vector of numbers. The structure contains the following members:

Values: 

continuous:

Whether the fitted power-law distribution was continuous or discrete.

alpha:

The exponent of the fitted power-law distribution.

xmin:

The minimum value from which the power-law distribution was fitted. In other words, only the values larger than xmin were used from the input vector.

L:

The log-likelihood of the fitted parameters; in other words, the probability of observing the input vector given the parameters.

D:

The test statistic of a Kolmogorov-Smirnov test that compares the fitted distribution with the input vector. Smaller scores denote better fit.

p:

The p-value of the Kolmogorov-Smirnov test. Small p-values (less than 0.05) indicate that the test rejected the hypothesis that the original data could have been drawn from the fitted power-law distribution.

6.2. igraph_power_law_fit — Fits a power-law distribution to a vector of numbers

int igraph_power_law_fit(const igraph_vector_t* data, igraph_plfit_result_t* result,
                         igraph_real_t xmin, igraph_bool_t force_continuous);

This function fits a power-law distribution to a vector containing samples from a distribution (that is assumed to follow a power-law of course). In a power-law distribution, it is generally assumed that P(X=x) is proportional to x-alpha, where x is a positive number and alpha is greater than 1. In many real-world cases, the power-law behaviour kicks in only above a threshold value xmin. The goal of this functions is to determine alpha if xmin is given, or to determine xmin and the corresponding value of alpha.

The function uses the maximum likelihood principle to determine alpha for a given xmin; in other words, the function will return the alpha value for which the probability of drawing the given sample is the highest. When xmin is not given in advance, the algorithm will attempt to find the optimal xmin value for which the p-value of a Kolmogorov-Smirnov test between the fitted distribution and the original sample is the largest. The function uses the method of Clauset, Shalizi and Newman to calculate the parameters of the fitted distribution. See the following reference for details:

Aaron Clauset, Cosma R .Shalizi and Mark E.J. Newman: Power-law distributions in empirical data. SIAM Review 51(4):661-703, 2009.

Arguments: 

data:

vector containing the samples for which a power-law distribution is to be fitted. Note that you have to provide the samples, not the probability density function or the cumulative distribution function. For example, if you wish to fit a power-law to the degrees of a graph, you can use the output of igraph_degree directly as an input argument to igraph_power_law_fit

result:

the result of the fitting algorithm. See igraph_plfit_result_t for more details.

xmin:

the minimum value in the sample vector where the power-law behaviour is expected to kick in. Samples smaller than xmin will be ignored by the algorithm. Pass zero here if you want to include all the samples. If xmin is negative, the algorithm will attempt to determine its best value automatically.

force_continuous:

assume that the samples in the data argument come from a continuous distribution even if the sample vector contains integer values only (by chance). If this argument is false, igraph will assume a continuous distribution if at least one sample is non-integer and assume a discrete distribution otherwise.

Returns: 

Error code: IGRAPH_ENOMEM: not enough memory IGRAPH_EINVAL: one of the arguments is invalid IGRAPH_EOVERFLOW: overflow during the fitting process IGRAPH_EUNDERFLOW: underflow during the fitting process IGRAPH_FAILURE: the underlying algorithm signaled a failure without returning a more specific error code

Time complexity: in the continuous case, O(n log(n)) if xmin is given. In the discrete case, the time complexity is dominated by the complexity of the underlying L-BFGS algorithm that is used to optimize alpha. If xmin is not given, the time complexity is multiplied by the number of unique samples in the input vector (although it should be faster in practice).

Example 33.4.  File examples/simple/igraph_power_law_fit.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>

void print_result(const igraph_plfit_result_t* result) {
    printf("continuous = %s\n", result->continuous ? "true" : "false");
    printf("alpha = %.5f\n", result->alpha);
    printf("xmin = %.5f\n", result->xmin);
    printf("L = %.5f\n", result->L);
    printf("D = %.5f\n", result->D);
    printf("p = %.5f\n", result->p);
    printf("====================\n");
}

int test_continuous() {
    igraph_plfit_result_t result;
    igraph_vector_t vector;
    double data[] = { 1.52219974, 6.80675663, 1.02798042, 1.31180733, 3.97473174,
                      1.17209342, 1.64889191, 2.47764721, 1.32939375, 3.03762554, 1.62638327,
                      6.08405495, 1.70890382, 1.05294973, 1.17408407, 4.48945532, 1.16777371,
                      2.52502391, 1.09755984, 1.63838051, 1.03811206, 1.47224168, 1.57161431,
                      1.60163451, 2.08280263, 1.04678340, 1.33317526, 1.58588741, 1.26484666,
                      1.02367503, 1.57045702, 3.42374138, 1.23190611, 1.09378228, 1.04959505,
                      1.05818408, 1.43879491, 2.22750459, 1.41027204, 1.81964745, 2.80239939,
                      1.25399323, 1.07479219, 3.94616077, 1.26367914, 1.87367507, 1.35741026,
                      1.14867526, 7.33024762, 1.87957274, 2.79258534, 1.21682159, 1.61194300,
                      2.81885973, 1.21514746, 1.12850917, 51.85245035, 1.21883209, 1.04861029,
                      1.69215609, 2.18429429, 1.59752172, 1.41909984, 3.14393355, 1.18298455,
                      1.67063821, 1.88568524, 1.07445906, 1.45007973, 1.12568920, 1.56806310,
                      1.36996101, 1.19440982, 6.57296980, 1.35860725, 1.06552137, 1.16950701,
                      1.34750790, 1.66977492, 1.22658722, 1.62247444, 1.23458784, 8.55843760,
                      1.70020162, 4.76368831, 1.04846170, 1.13689661, 1.94449567, 1.10584812,
                      1.32525767, 1.26640912, 1.91372972, 1.56185373, 2.37829675, 1.04616674,
                      2.43549177, 1.14961092, 1.82106455, 1.25818298, 1.64763037, 1.43019402,
                      1.50439978, 1.90281251, 1.34827040, 1.57935671, 1.77260751, 1.06976614,
                      1.12236012, 2.19770254, 1.51825533, 1.19027804, 1.08307524, 1.57912902,
                      3.33313888, 2.14005088, 1.38341873, 1.20088138, 1.25870539, 1.03811620,
                      1.86622820, 2.99310953, 1.55615055, 2.12364873, 4.49081000, 1.01274439,
                      1.22373389, 3.79059729, 3.10099275, 2.70218546, 1.03609624, 2.20776919,
                      1.00651347, 1.87344592, 1.04903307, 1.24899747, 1.20377911, 1.12706494,
                      1.01706713, 7.01069306, 1.05363146, 2.50105512, 1.11168552, 1.71133998,
                      1.17714528, 1.37986755, 2.20981534, 1.18179277, 2.07982010, 4.04967099,
                      1.00680257, 1.62850069, 2.58816230, 1.35079027, 1.03382890, 4.54326500,
                      1.62489905, 1.36102570, 1.52349738, 1.06606346, 7.80558026, 1.02602538,
                      1.43330925, 1.36040920, 9.29692547, 15.27015690, 1.75966437, 1.02635409,
                      1.40421505, 2.87296958, 1.46232202, 1.87065204, 3.37278803, 1.82589564,
                      1.06488044, 1.72568108, 1.21062115, 4.39311214, 1.12636227, 2.20820528,
                      1.09826903, 2.58989998, 1.34944949, 1.08654244, 2.38021951, 3.96308780,
                      1.37494639, 1.18245279, 3.72506217, 3.79775023, 1.19018356, 2.86924476,
                      3.40015888, 1.92317855, 1.55203754, 1.34985008, 1.31480190, 1.65899877,
                      4.77446435, 1.41073246, 1.35555456, 2.40543613, 2.72162935, 1.34475982,
                      1.41342115, 5.15278473, 1.69654436, 3.21081899, 1.18822397, 1.40394863,
                      1.06793574, 1.67085563, 1.08125975, 1.11765459, 1.17245045, 1.15711479,
                      1.18656910, 1.61296203, 1.71427634, 1.24017302, 2.05291524, 2.52658791,
                      2.04645295, 34.07541626, 1.32670899, 1.03893757, 1.08957199, 5.55332328,
                      1.17276097, 1.60389480, 2.02098430, 2.92934928, 1.00558653, 1.05830070,
                      1.81440889, 3.85044779, 1.12317456, 1.39547640, 2.93105179, 1.95048788,
                      1.05602445, 1.96855429, 1.60432293, 3.28820202, 1.50117325, 1.19775674,
                      1.28280841, 1.08318646, 1.02098264, 1.24861938, 1.06511473, 1.07549717,
                      3.57739126, 1.07265409, 1.06312441, 1.16296512, 3.83654484, 2.02366951,
                      1.73168875, 1.60443228, 2.30779766, 1.50531775, 1.31925607, 1.87926179,
                      1.86249354, 2.14768716, 2.31583955, 2.15651148, 1.29677318, 1.10110071,
                      1.03383916, 1.50665009, 1.16502917, 1.40055008, 2.80847193, 1.29824634,
                      2.76239920, 1.73123621, 1.15286577, 1.89493526, 1.63112634, 1.17828846,
                      1.01293513, 1.84834048, 4.19026736, 1.82684815, 3.51812301, 1.33499862,
                      2.03087497, 1.32419883, 1.34126954, 1.98250684, 1.00025697, 1.59416883,
                      6.38249787, 2.79055559, 1.57750678, 1.36953983, 1.37513919, 3.63573178,
                      1.15637432, 9.28386344, 1.16947695, 1.54995742, 1.44018755, 1.29332881,
                      1.81274872, 1.14900153, 1.07117403, 1.17035915, 1.39229249, 1.96645872,
                      1.09147706, 1.25211993, 1.07092474, 1.85394206, 1.29807741, 3.41499510,
                      1.22444449, 1.00913782, 3.87431854, 1.01072376, 1.01186727, 3.00175639,
                      2.52183377, 1.23992099, 1.69819010, 1.36850400, 1.14577814, 1.06035078,
                      1.08414298, 1.55920217, 5.07059630, 1.15434572, 1.41873305, 1.24712256,
                      1.10478618, 1.30707247, 1.85719110, 1.89873207, 1.72629431, 1.65171651,
                      7.10864875, 2.31945709, 1.06722361, 1.26696259, 2.23845503, 1.38674196,
                      1.91015397, 1.29590323, 1.10448028, 4.52757499, 2.00258408, 1.38299092,
                      1.01431427, 1.54039270, 1.34880396, 1.08784083, 1.35553378, 1.37307373,
                      1.32320467, 1.50261683, 6.91050685, 1.06083157, 1.20841351, 2.92719840,
                      2.82178183, 2.05765813, 1.84621661, 1.04677388, 2.13801850, 1.39654855,
                      1.13037727, 1.37887598, 1.03221650, 1.15981176, 1.09896163, 1.88624084,
                      1.43459062, 1.54587662, 1.48604380, 2.06197392, 1.97079675, 4.31388672,
                      2.94376994, 3.48708489, 1.09674551, 2.46926816, 1.23705940, 1.57512843,
                      1.15595205, 1.18432818, 1.54298936, 1.60600489, 1.07361787, 1.38666771,
                      1.45533003, 1.78940830, 1.33799752, 1.12955889, 4.59400278, 1.15170228,
                      1.39346636, 1.61408789, 2.21293753, 5.33166143, 1.18147947, 1.54426891,
                      1.32496426, 1.25037632, 3.31244261, 1.36211171, 1.82239599, 1.75235087,
                      1.67044831, 1.24802350, 1.34776327, 1.34740665, 1.30664120, 1.06852680,
                      1.22513631, 1.25310923, 1.36394926, 1.07796356, 3.10823551, 1.46770227,
                      1.40264883, 1.08787681, 1.26460358, 1.10348946, 2.03168839, 1.09435135,
                      1.66991715, 1.19738540, 1.28922229, 2.85704149, 1.33952521, 1.73497688,
                      2.90052876, 5.34596348, 1.36399078, 3.38399264, 1.06089658, 1.09370142,
                      1.37523679, 3.01964907, 1.40684792, 1.11312672, 2.44666372, 1.73953904,
                      1.65569280, 1.05813000, 2.02893022, 1.72877601, 1.55758690, 1.83904301,
                      1.14316984, 1.17792251, 1.44106281, 9.67126482, 1.93207441, 1.08242887,
                      2.87271135, 2.19095115, 2.13195479, 1.02355472, 1.18218470, 1.30907724,
                      1.13291587, 2.85659336, 12.62726889, 1.18818589, 1.02852443, 1.12838670,
                      1.36349361, 1.34817100, 1.30535737, 3.22225028, 1.28680350, 1.83979657,
                      1.11088952, 1.43866586, 8.52587567, 3.73988696, 2.65816056, 1.17373111,
                      2.61567111, 3.24024082, 2.96798864, 1.05335616, 1.31159271, 1.36485918,
                      1.24988767, 7.80609746, 1.54892174, 1.10682809, 1.21728827, 1.20429971,
                      1.72719055, 1.78534831, 1.04414979, 1.25646988, 1.19788383, 1.08854812,
                      1.04859628, 1.04676064, 5.07295341, 3.83595341, 1.61079632, 1.10528426,
                      1.15050241, 2.78129736, 1.25494119, 1.28692155, 1.06812292, 3.29393761,
                      1.37542463, 1.67241953, 1.21698665, 10.57727604, 8.63598976, 1.18886984,
                      1.30609583, 9.47777457, 1.69612900, 2.23002585, 1.58461615, 1.04110023,
                      3.08140806, 1.39599251, 1.06575789, 1.29741002, 1.75253864, 1.82594258,
                      1.15111702, 1.17370053, 1.15254396, 1.94401179, 5.36344596, 4.66322185,
                      1.15073993, 3.21478159, 1.39843306, 1.03961906, 5.72845289, 1.72454161,
                      1.04610704, 1.38975310, 1.77732797, 1.10139931, 2.23656355, 1.89952669,
                      1.72136921, 1.15798212, 1.59545971, 1.08789161, 1.93272206, 2.57480708,
                      1.04977784, 2.00874078, 3.40065861, 1.00978603, 3.97804652, 1.54762586,
                      1.01015493, 1.15148220, 1.15246483, 19.67426012, 1.33290993, 2.33137522,
                      1.12841749, 1.73407057, 2.00469493, 1.27418995, 1.49814918, 1.10398785,
                      1.20063760, 1.05536150, 1.87616599, 1.49305736, 1.60241346, 1.16666060,
                      1.05013736, 1.77929210, 1.00206028, 3.41096863, 1.47499925, 1.14071240,
                      1.65361002, 1.76466424, 8.49298111, 1.41069285, 2.11681605, 4.90260842,
                      1.13029658, 1.20802818, 1.42525579, 1.00310774, 1.08082363, 9.95194247,
                      2.82773946, 2.77420002, 1.82543685, 1.28557906, 1.97711769, 1.19001264,
                      1.95712650, 1.54230291, 1.31625757, 2.36364128, 1.11523099, 1.00343756,
                      1.71299382, 1.44667100, 2.38154868, 1.41174217, 1.80660493, 1.51020853,
                      1.16761479, 1.25898190, 1.18150781, 1.58465451, 2.03560597, 3.48531184,
                      1.21187672, 1.35111036, 1.02954922, 1.90892663, 3.99078548, 5.67385199,
                      4.38055264, 1.17446048, 13.41617858, 1.60241740, 1.14811206, 4.68120263,
                      3.83763710, 2.66095263, 1.83338503, 4.75973082, 1.08982301, 4.04104276,
                      1.34220189, 1.06135891, 2.71185882, 1.46085873, 1.09915614, 10.35178646,
                      2.54402271, 2.65696704, 1.31388649, 1.02942408, 1.57780748, 1.01552697,
                      2.24860361, 2.22011778, 1.13595134, 1.11492512, 2.11966788, 1.20420149,
                      1.11112428, 3.09324603, 2.87240762, 1.50486558, 1.92227231, 4.12480449,
                      1.58244751, 1.69922308, 6.28134904, 2.91944178, 1.85386792, 1.41799519,
                      1.64636127, 2.05837832, 1.07153521, 2.05376943, 2.60053549, 1.09773382,
                      1.54671309, 1.68007415, 3.43941489, 1.41601033, 2.00237256, 1.20830978,
                      1.25582363, 1.10830461, 1.24850906, 1.88035202, 1.70557719, 1.04191110,
                      1.33501003, 1.33554804, 1.36935735, 4.79153510, 1.06566392, 1.14495966,
                      1.90020028, 1.08266994, 1.20588153, 1.40730214, 4.34320304, 1.71762330,
                      1.06620797, 1.39695239, 1.03024563, 3.94971225, 5.02945862, 1.06145571,
                      1.42511911, 2.13889169, 1.04986044, 1.91400616, 5.50708156, 1.52870464,
                      1.11303137, 1.05282759, 1.83793940, 3.05244089, 2.64499634, 1.51688076,
                      2.63350152, 1.31014486, 1.69462474, 1.67792130, 1.34236945, 1.02358460,
                      1.04593509, 1.04007620, 1.87990081, 1.28585413, 1.01636283, 3.55338495,
                      1.19542700, 1.23630628, 1.32321942, 4.03762786, 1.25379147, 1.12330233,
                      1.24966418, 1.26323243, 1.14779989, 1.20378343, 1.01531796, 1.44500318,
                      1.72723672, 15.68799957, 1.37641063, 7.00788166, 3.89674130, 1.68303382,
                      1.10089816, 1.72831362, 2.70479861, 1.75821836, 2.32404215, 2.64165162,
                      1.42441301, 1.83256456, 1.12548819, 4.81273800, 2.52840227, 2.68430190,
                      1.00928919, 1.02438446, 1.33909276, 2.32261242, 1.01299124, 1.07614975,
                      1.66823898, 1.97172786, 1.01707292, 1.68325092, 1.76834032, 1.08952069,
                      1.02265517, 1.96843176, 1.83351706, 1.92704772, 18.44811035, 1.00178046,
                      2.70555953, 1.35839004, 1.04834633, 1.26649072, 2.87152600, 4.12536409,
                      1.25200853, 1.71199647, 1.61175739, 1.26313274, 1.75224120, 2.70412800,
                      1.33998630, 1.61271556, 2.65784769, 10.38771107, 1.33121364, 1.01207979,
                      2.00238212, 2.50195600, 1.96917548, 1.71618169, 1.37050585, 10.11861690,
                      1.18339112, 1.80083386, 2.88582103, 1.21935761, 2.37900131, 1.49449487,
                      4.75106319, 2.33977804, 2.87963540, 1.01807103, 3.74847411, 1.71981276,
                      1.50726964, 1.20723219, 1.37904840, 1.04565533, 1.59877004, 1.11481349,
                      2.17320556, 2.07108468, 1.23274077, 1.75180110, 1.27558910, 1.63240839,
                      1.58760550, 1.01266256, 1.30395323, 1.14618521, 1.02385023, 2.24198100,
                      1.26765471, 1.15855534, 1.83936251, 1.32970987, 1.25844192, 1.31133485,
                      4.74300303, 6.19325623, 1.31832913, 3.97645560, 1.00545340, 1.24431862,
                      1.25855820, 1.15514241, 1.35986865, 1.72446070, 1.13069572, 2.45890932,
                      1.00394684, 1.03533631, 1.87698184, 2.34576160, 1.03997887, 1.02694456,
                      2.52227100, 2.66278467, 1.17002905, 3.42239624, 2.46753038, 1.17103623,
                      1.07832850, 1.42782632, 1.29110546, 1.03435772, 1.33512109, 1.14337058,
                      1.34103634, 1.15155161, 2.59805360, 2.09650343, 1.53399143, 1.02319185,
                      1.32210667, 1.05720671, 1.20882651, 2.34881662, 1.05163662, 3.26219380,
                      10.58124156, 1.07283644, 1.02105339, 1.23268679, 1.81469813, 1.49393533,
                      1.29760853, 5.37676625, 1.02529938, 1.86815537, 1.57961476, 3.77408176,
                      2.79405589, 3.25246617, 1.63913824, 3.12133428, 1.03787574, 4.17232960,
                      1.33406468, 1.57119541, 1.13675102, 3.42874720, 1.13066210, 1.33896458,
                      1.23883935, 1.35272696, 1.15172654, 2.18633755, 1.23251881, 1.59742606,
                      1.08718410, 1.06168544, 1.19926517, 1.00214807, 1.29121086, 3.44575916,
                      1.26524744, 1.16718301, 4.11789988, 1.25375574, 1.35753968, 1.69247751,
                      1.28473150, 2.20669768, 1.53213883, 2.30598771, 1.68420243, 1.37320685,
                      2.08619411, 1.26990265, 1.82215898, 1.10656122, 1.40229835, 1.11896817,
                      1.00127366, 2.88218857, 2.79105702, 1.28699225, 1.15929737, 1.07928363,
                      10.54130128, 8.79261793, 1.15699405, 1.69050500, 2.76586152, 1.22802809,
                      1.38014655, 2.19208585, 1.64409370, 1.46918371, 2.99582898, 1.37759923,
                      1.29776632, 1.82884215, 2.67317357, 1.37063041, 1.26884340, 1.07874723,
                      1.48172681, 1.01771849, 2.40642202, 1.37115433, 1.05954574, 2.12998246,
                      2.34178079, 1.54515623, 1.00179963, 2.12228030, 1.46007334, 1.20664530,
                      1.31417158, 1.03322353, 1.95420119, 1.30541569, 1.15016102, 2.17036908,
                      2.81707947, 1.16173181, 2.01742565, 1.02478594, 1.57428560, 1.21209176,
                      2.20735202, 1.12935761, 2.08850147, 1.05353378, 1.02324910, 1.49636415,
                      1.48061026, 2.25651770, 3.04296168, 1.24380806, 1.07707360, 2.00284318,
                      10.02810932, 3.38695326, 6.82841534, 2.13556915, 1.19152238
                    };

    igraph_vector_view(&vector, data, sizeof(data) / sizeof(data[0]));

    /* determining xmin and alpha */
    if (igraph_power_law_fit(&vector, &result, -1, 0)) {
        return 1;
    }
    print_result(&result);

    /* determining alpha only */
    if (igraph_power_law_fit(&vector, &result, 2, 0)) {
        return 2;
    }
    print_result(&result);

    return 0;
}

int test_discrete() {
    igraph_plfit_result_t result;
    igraph_vector_t vector;
    double data[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
                      2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1,
                      1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1,
                      1, 1, 1, 1, 1, 1, 6, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 4, 1, 1, 1,
                      1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1,
                      1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1,
                      1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
                      1, 2, 1, 4, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 4, 1, 1, 14, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 2,
                      1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1,
                      1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 4, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 2, 5, 1, 1, 5, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 3, 1, 1,
                      2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1,
                      2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1,
                      1, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2,
                      1, 1, 1, 1, 2, 11, 1, 33, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2,
                      2, 1, 1, 1, 2, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1,
                      1, 1, 2, 1, 2, 1, 1, 12, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
                      3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 2, 1, 4, 1, 1, 1, 1, 1,
                      1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
                      1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                      1, 2, 2, 2, 2, 1, 1, 1, 4, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
                      3, 2, 1, 1, 1, 2
                    };

    igraph_vector_view(&vector, data, sizeof(data) / sizeof(data[0]));

    /* determining xmin and alpha */
    if (igraph_power_law_fit(&vector, &result, -1, 0)) {
        return 3;
    }
    print_result(&result);

    /* determining alpha only */
    if (igraph_power_law_fit(&vector, &result, 2, 0)) {
        return 4;
    }
    print_result(&result);

    /* forcing continuous fitting */
    if (igraph_power_law_fit(&vector, &result, -1, 1)) {
        return 5;
    }
    print_result(&result);

    /* forcing continuous fitting, xmin given */
    if (igraph_power_law_fit(&vector, &result, 2, 1)) {
        return 6;
    }
    print_result(&result);

    return 0;
}

int main() {
    int retval;

    retval = test_continuous();
    if (retval) {
        return retval;
    }

    retval = test_discrete();
    if (retval) {
        return retval;
    }

    return 0;
}