#ifndef __STDLIB_H__
# define __STDLIB_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>
#include <bits/exit.h>

/* Dynamic memory management. */

/* Allocate SIZE bytes of memory. */
extern void *malloc(size_t __size);

/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern void *calloc(size_t __nmemb, size_t __size);

/*
** Re-allocate the previously allocated block in PTR, making the new block
** SIZE bytes long.
*/
extern void *realloc(void *__ptr, size_t __size);

/*
** Re-allocate the previously allocated block in PTR, making the new block large
** enough for NMEMB elements of SIZE bytes each.
*/
extern void *reallocarray(void *__ptr, size_t __nmemb, size_t __size);

/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free(void *__ptr);

/* Communication with the environment. */

/* Abort execution; raises SIGABRT and leaves quickly with _Exit(). */
__attribute__((noreturn))
extern void abort(void);

/* Exit; calls handlers, flushes and closes streams and temporary files. */
__attribute__((noreturn))
extern void exit(int __status);

/* Exit immediately, bypassing exit handlers or signal handlers. */
__attribute__((noreturn))
extern void _Exit(int __status);

/* Integer arithmetic functions. */

extern int abs(int __j);
#define abs(j) ({ \
	int __j = (j); \
	(__j >= 0) ? __j : -(__j); \
})

extern long int labs(long int __j);
#define labs(j) ({ \
	long int __j = (j); \
	(__j >= 0) ? __j : -(__j); \
})

extern long long int llabs(long long int __j);
#define llabs(j) ({ \
	long long int __j = (j); \
	(__j >= 0) ? __j : -(__j); \
})

typedef struct {
	int quot, rem;
} div_t;

typedef struct {
	long int quot, rem;
} ldiv_t;

typedef struct {
	long long int quot, rem;
} lldiv_t;

extern div_t div(int __num, int __denom);
extern ldiv_t ldiv(long int __num, long int __denom);
extern lldiv_t lldiv(long long int __num, long long int __denom);

/* Simplified numeric conversion functions. */

/* ASCII to int. */
extern int atoi(char const *__ptr);

/* ASCII to long int. */
extern long int atol(char const *__ptr);

/* ASCII to long long int. */
extern long long int atoll(char const *__ptr);

/* Numeric conversion functions. */

/* ASCII to floating-point. */
extern double atof(char const *__ptr);

/* Parse a long int from a string. */
extern long int strtol(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr,
	int __base);

/* Parse a long unsigned int from a string. */
extern unsigned long int strtoul(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr,
	int __base);

/* Parse a long long int from a string. */
extern long long int strtoll(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr,
	int __base);

/* Parse a long long unsigned int from a string. */
extern unsigned long long int strtoull(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr,
	int __base);

/* Parse a double from a string. */
extern double strtod(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr);

/* Parse a float from a string. */
extern float strtof(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr);

/* Parse a long double from a string. */
extern long double strtold(
	char const * __restrict__ __ptr,
	char ** __restrict__ __endptr);

/* Pseudo-random sequence generation functions. */

#define RAND_MAX 0x7fffffff

/* Seed the PRNG. */
extern void srand(unsigned int seed);

/* Generate a pseudo-random number between 0 and RAND_MAX. */
extern int rand(void);

/* Searching and sorting utilities. */

void qsort(void *base, size_t nmemb, size_t size,
	int (*compare)(void const *left, void const *right));

#ifdef __cplusplus
}
#endif

#endif /*__STDLIB_H__*/