/*
 *
 * gengraph - generation of random simple connected graphs with prescribed
 *            degree sequence
 *
 * Copyright (C) 2006  Fabien Viger
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */
#ifndef DEFINITIONS_H
#define DEFINITIONS_H

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

#include "igraph_types.h"
#include "internal/hacks.h"

namespace gengraph {

// Max line size in files
#define FBUFF_SIZE 1000000

// disable lousy VC++ warnings
#ifdef _ATL_VER_
    #pragma warning(disable : 4127)
#endif //_ATL_VER_

// Verbose
#define VERBOSE_NONE 0
#define VERBOSE_SOME 1
#define VERBOSE_LOTS 2
int VERBOSE();
void SET_VERBOSE(int v);

// Random number generator
void my_srandom(int);
long my_random();
int my_binomial(double pp, int n);
double my_random01(); // (0,1]

#define MY_RAND_MAX 0x7FFFFFFF

//inline double round(double x) throw () { return (floor(0.5+x)); }

// Min & Max
#ifndef min
    #define defmin(type) inline type min(type a, type b) { return a<b ? a : b; }
    defmin(int)
    defmin(double)
    defmin(unsigned long)
    defmin(long long)
#endif //min
#ifndef max
    #define defmax(type) inline type max(type a, type b) { return a>b ? a : b; }
    defmax(int)
    defmax(double)
    defmax(unsigned long)
    defmax(long long)
#endif //max

// Debug definitions
//#define PERFORMANCE_MONITOR
//#define OPT_ISOLATED

// Max Int
#ifndef MAX_INT
    #define MAX_INT 0x7FFFFFFF
#endif //MAX_INT

//Edge type
typedef struct {
    igraph_integer_t from;
    igraph_integer_t to;
} edge;

// Tag Int
#define TAG_INT 0x40000000

// Oldies ....
#define S_VECTOR_RAW

//*********************
// Routine definitions
//*********************

/* log(1+x)
inline double logp(double x) {
  if(fabs(x)<1e-6) return x+0.5*x*x+0.333333333333333*x*x*x;
  else return log(1.0+x);
}
*/


//Fast search or replace
inline igraph_integer_t* fast_rpl(igraph_integer_t *m, igraph_integer_t a, igraph_integer_t b) {
    while (*m != a) {
        m++;
    }
    *m = b;
    return m;
}
inline igraph_integer_t* fast_search(igraph_integer_t *m, igraph_integer_t size, igraph_integer_t a) {
    igraph_integer_t *p = m + size;
    while (m != p--) {
        if (*p == a) {
            return p;
        }
    }
    return NULL;
}

// Lovely percentage print
// inline void print_percent(double yo, FILE *f = stderr) {
//   int arf = int(100.0*yo);
//   if(double(arf)>100.0*yo) arf--;
//   if(arf<100) fprintf(f," ");
//   if(arf<10) fprintf(f," ");
//   fprintf(f,"%d.%d%%",arf,int(1000.0*yo-double(10*arf)));
// }

// Skips non-numerical chars, then numerical chars, then non-numerical chars.
inline char skip_int(char* &c) {
    while (*c < '0' || *c > '9') {
        c++;
    }
    while (*c >= '0' && *c <= '9') {
        c++;
    }
    while (*c != 0 && (*c < '0' || *c > '9')) {
        c++;
    }
    return *c;
}

// distance+1 modulo 255 for breadth-first search
inline unsigned char next_dist(const unsigned char c) {
    return c == 255 ? 1 : c + 1;
}
inline unsigned char prev_dist(const unsigned char c) {
    return c == 1 ? 255 : c - 1;
}

// 1/(RANDMAX+1)
#define inv_RANDMAX (1.0/(1.0+double(MY_RAND_MAX)))

// random number in ]0,1[, _very_ accurate around 0
inline double random_float() {
    long r = my_random();
    double mul = inv_RANDMAX;
    while (r <= 0x7FFFFF) {
        r <<= 8;
        r += (my_random() & 0xFF);
        mul *= (1.0 / 256.0);
    }
    return double(r) * mul;
}

// Return true with probability p. Very accurate when p is small.
#define test_proba(p) (random_float()<(p))

// Random bit generator, sparwise.
static int _random_bits_stored = 0;
static long _random_bits = 0;

inline int random_bit() {
    long a = _random_bits;
    _random_bits = a >> 1;
    if (_random_bits_stored--) {
        return a & 0x1;
    }
    a = my_random();
    _random_bits = a >> 1;
    _random_bits_stored = 30;
    return a & 0x1;
}

// Hash Profiling (see hash.h)
void _hash_prof();

} // namespace gengraph

#endif //DEFINITIONS_H
