Files
mlpack/fastlib/base/common.h
T
2008-01-21 03:10:03 +00:00

288 lines
8.5 KiB
C

// Copyright 2007 Georgia Institute of Technology. All rights reserved.
/**
* @file common.h
*
* The bare necessities of FASTlib programming in C, including
* standard types, formatted messages to stderr, and useful libraries
* and compiler directives.
*
* This file should be included before all built-in libraries because
* it includes the _REENTRANT definition needed for thread-safety.
* Files base.h or fastlib.h include this file first and may serve as
* surrogates.
*
* @see compiler.h
*/
#ifndef BASE_COMMON_H
#define BASE_COMMON_H
#ifndef _REENTRANT
#define _REENTRANT
#endif
#include "base/basic_types.h"
#include "compiler.h"
#include "ansi_colors.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>
EXTERN_C_BEGIN
/** A no-op used in some macros. */
#define NOP ((void)0)
/* Types and definitions to assist managment of problem scale. */
/* Ensure that one and only one problem scale is selected. */
#if defined(SCALE_MASSIVE)
#if defined(SCALE_LARGE) || defined(SCALE_NORMAL)
#error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined.
#endif
#elif defined(SCALE_LARGE)
#if defined(SCALE_NORMAL)
#error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined.
#endif
#elif !defined(SCALE_NORMAL)
#define SCALE_NORMAL
#endif
/**
* Index type used in FASTlib for array sizes, etc.
*
* Define one of the following (default SCALE_NORMAL):
*
* SCALE_NORMAL - Problems are as large can be indexed with your
* machine's standard integers. As of 2007, this is 32 bits.
*
* SCALE_LARGE - Problems are as large as your machine's architecture
* can support. Unless you have more than 2 billion data points,
* this will waste some space and reduce cache efficiency.
*
* SCALE_MASSIVE - Problems are 64-bit indexed even on 32-bit
* machines, rendering them larger than RAM.
*
* Values are signed to allow uninitialized indices of -1 as well as
* consideration of potentially negative differences between indices.
*/
#if defined(SCALE_MASSIVE)
typedef int64 index_t; /* For larger than RAM data sets. */
#elif defined(SCALE_LARGE)
typedef ssize_t index_t; /* As large as this machine can handle. */
#elif defined(SCALE_NORMAL)
typedef int index_t; /* Normal sized data; usually 32-bit. */
#endif
/**
* Length modifier for emitting index_t with printf.
*
* Example:
* @code
* index_t i = 42;
* printf("%"LI"d\n", i);
* @endcode
*/
#if defined(SCALE_MASSIVE)
#define LI L64
#elif defined(SCALE_LARGE)
#define LI "l" /* TODO: confirm correct. */
#elif defined(SCALE_NORMAL)
#define LI ""
#endif
/** Size of a kilobyte in bytes. */
#define KILOBYTE (((size_t)1) << 10)
/** Size of a megabyte in bytes. */
#define MEGABYTE (((size_t)1) << 20)
/** Size of a gigabyte in bytes. */
#define GIGABYTE (((size_t)1) << 30)
/* Add more of these as necessary. */
/* Tools for FASTlib stderr messages, warnings, and errors. */
/** Whether to segfault instead of calling C's abort(). */
extern int segfault_on_abort;
/** Whether to treat nonfatal warnings as fatal. */
extern int abort_on_nonfatal;
/** Whether to wait for user input after nonfatal warnings. */
extern int pause_on_nonfatal;
/** Whether to print call locations for notifications. */
extern int print_notify_locs;
/** Different types of messages FASTlib prints to stderr. */
typedef enum {
/** Message for an unrecoverable error. */
FL_MSG_FATAL = 0,
/** Message for a potentially recoverable warning. */
FL_MSG_NONFATAL = 1,
/** Message for a significant but non-problematic event. */
FL_MSG_NOTIFY_STAR = 2,
/** Message for a standard, non-problematic event. */
FL_MSG_NOTIFY = 3
} fl_msg_t;
/** Default markers for FASTlib messages. */
extern char fl_msg_marker[];
/** Default colors for FASTlib message markers. */
extern const char * fl_msg_color[];
/**
* Terminates with an error, flushing all streams.
*
* Behavior adjustable with segfault_on_abort, which may be handy for
* valgrind or other debuggers.
*/
COMPILER_NO_RETURN
void fl_abort(void);
/**
* Waits for the user to press return.
*
* This function will obliterate anything in the stdin buffer.
*/
void fl_pause(void);
/** Prints a colored message header. */
void fl_print_msg_header(char marker, const char *color);
/** Print a location in code. */
void fl_print_msg_loc(const char *file, const char *func, int line);
/** Implementation for FATAL. */
COMPILER_NO_RETURN
COMPILER_PRINTF(4, 5)
void fl_print_fatal_msg(const char *file, const char *func, int line,
const char* format, ...);
/** Implementation for NONFATAL, NOTIFY_STAR, and NOTIFY. */
COMPILER_PRINTF(5, 6)
void fl_print_msg(const char *file, const char *func, int line,
fl_msg_t msg_type, const char* format, ...);
/**
* Aborts, printing call location and a message to stderr.
*
* @param msg_params format string and variables, as in printf
*/
#define FATAL(msg_params...) (fl_print_fatal_msg( \
__FILE__, __FUNCTION__, __LINE__, msg_params))
/**
* (Possibly) aborts or pauses, printing call location and a message
* to stderr.
*
* @param msg_params format string and variables, as in printf
*/
#define NONFATAL(msg_params...) (fl_print_msg( \
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NONFATAL, msg_params))
/**
* Prints (possibly) call location and a message with special marker
* to stderr.
*
* @param msg_params format string and variables, as in printf
*/
#define NOTIFY_STAR(msg_params...) (fl_print_msg( \
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY_STAR, msg_params))
/**
* Prints (possibly) call location and a message with standard marker
* to stderr.
*
* @param msg_params format string and variables, as in printf
*/
#define NOTIFY(msg_params...) (fl_print_msg( \
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY, msg_params))
/**
* Prints a progress bar using ANSI commands to stay in place.
*
* For proper formatting, desc should be 22 characters or fewer and
* the program should avoid output of other text while emitting a
* progress bar. When finished with a progress bar, emit a newline
* ('\n') to keep the bar on screen or a line of spaces followed by a
* carriage return ('\r') to clear it.
*
* @param name printed next to the progress bar; max 22 characters
* @param perc percentage of bar filled; should range from 0 to 100
*/
void fl_print_progress(const char *name, int perc);
/* Tools for expressing success or failure of FASTlib functions. */
/**
* Type for indicating success or failure.
*
* Return these rather than ints to indicate your functions' results;
* ints are interchangeably interpreted with either zero or nonzero
* for success, but values of this type have fixed meaning.
*
* You may extend the meaning of this type in your code by instead
* returning integer values other than SUCCESS_FAIL or SUCCESS_PASS,
* but ensure that all failure values are less than or equal to
* SUCCESS_FAIL, all success values are greater than or equal to
* SUCCESS_PASS, and all warning values are in between.
*
* Because the values given below are subject to change, special
* values should be expressed as deltas, e.g. SUCCESS_FAIL - 5. If
* you need more than 64 warning values, etc., consider instead using
* an additional pointer argument to return an error code.
*/
typedef enum {
/** Upper-bound value indicating failed operation. */
SUCCESS_FAIL = 63,
/** A generic warning value. */
SUCCESS_WARN = 96,
/** Lower-bound value indicating successful operation. */
SUCCESS_PASS = 128
} success_t;
/**
* True on SUCCESS_PASS or greater; false otherwise.
*
* Distinct from !FAILED(x). Optimized for the passing case.
*/
#define PASSED(x) (likely((x) >= SUCCESS_PASS))
/**
* True on SUCCESS_FAIL or less; false otherwise.
*
* Distinct from !PASSED(x). Optimized for the non-failing case.
*/
#define FAILED(x) (unlikely((x) <= SUCCESS_FAIL))
/**
* Asserts that an operation succeeds; otherwise, aborts.
*
* This optimized check occurs regardless of debug mode.
*/
#define MUST_PASS(x) \
(likely(x >= SUCCESS_PASS) ? NOP : FATAL("MUST_PASS failed: %s", #x))
/**
* Asserts that an operation does not fail; otherwise, aborts.
*
* This optimized check occurs regardless of debug mode.
*/
#define MUST_NOT_FAIL(x) \
(likely(x > SUCCESS_FAIL) ? NOP : FATAL("MUST_NOT_FAIL failed: %s", #x))
/** Converts C library non-negative success into a success_t. */
#define SUCCESS_FROM_C(x) (unlikely((x) < 0) ? SUCCESS_FAIL : SUCCESS_PASS)
EXTERN_C_END
#endif /* BASE_COMMON_H */