/* Copyright (c) 2000-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkma.h Mathematical operations. This module provides mathematical operations doing range checks. The final argument of dkma_..._ok functions is a pointer to an int variable receiving an error code if there were problems in the function. The variable is left as is if the function is successfull. Functions without ..._ok save error codes into an internal variable which can be requested and reset. These functions are not thread-safe. */ #ifndef DK_MA_INC #define DK_MA_INC #include #include #if defined(EXTERN) #undef EXTERN #endif #ifndef DK_MA_C #if !DK_HAVE_PROTOTYPES #define EXTERN extern #else #define EXTERN /* nix */ #endif #else #define EXTERN /* nix */ #endif #if defined(__cplusplus) extern "C" { #endif /** Retrieve last error code, optionally reset. Retrieve the error code of the last error from the module-internal variable. @param r Flag to indicate whether or not to reset the module-internal variable. @return The error code of the last error occured. */ EXTERN int dkma_get_error DK_PR((int r)); /** Addition of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Summary. */ EXTERN unsigned long dkma_add_ulong_ok DK_PR((unsigned long u1, unsigned long u2, int *ok)); /** Subtraction of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Difference. */ EXTERN unsigned long dkma_sub_ulong_ok DK_PR((unsigned long u1, unsigned long u2, int *ok)); /** Multiplication of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Product. */ EXTERN unsigned long dkma_mul_ulong_ok DK_PR((unsigned long u1, unsigned long u2, int *ok)); /** Division of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Result. */ EXTERN unsigned long dkma_div_ulong_ok DK_PR((unsigned long u1, unsigned long u2, int *ok)); /** Addition of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @return Summary. */ EXTERN unsigned long dkma_add_ulong DK_PR((unsigned long u1, unsigned long u2)); /** Subtraction of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @return Difference. */ EXTERN unsigned long dkma_sub_ulong DK_PR((unsigned long u1, unsigned long u2)); /** Multiplication of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @return Product. */ EXTERN unsigned long dkma_mul_ulong DK_PR((unsigned long u1, unsigned long u2)); /** Division of 2 unsigned long values. @param u1 Value 1. @param u2 Value 2. @return Result. */ EXTERN unsigned long dkma_div_ulong DK_PR((unsigned long u1, unsigned long u2)); /** Addition of 2 long values. @param l1 Value 1. @param l2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Summary. */ EXTERN long dkma_add_long_ok DK_PR((long l1, long l2, int *ok)); /** Subtraction of 2 long values. @param l1 Value 1. @param l2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Difference. */ EXTERN long dkma_sub_long_ok DK_PR((long l1, long l2, int *ok)); /** Multiplication of 2 long values. @param l1 Value 1. @param l2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Product. */ EXTERN long dkma_mul_long_ok DK_PR((long l1, long l2, int *ok)); /** Division of 2 long values. @param l1 Value 1. @param l2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Result. */ EXTERN long dkma_div_long_ok DK_PR((long l1, long l2, int *ok)); /** Addition of 2 long values. @param l1 Value 1. @param l2 Value 2. @return Summary. */ EXTERN long dkma_add_long DK_PR((long l1, long l2)); /** Subtraction of 2 long values. @param l1 Value 1. @param l2 Value 2. @return Difference. */ EXTERN long dkma_sub_long DK_PR((long l1, long l2)); /** Multiplication of 2 long values. @param l1 Value 1. @param l2 Value 2. @return Product. */ EXTERN long dkma_mul_long DK_PR((long l1, long l2)); /** Division of 2 long values. @param l1 Value 1. @param l2 Value 2. @return Result. */ EXTERN long dkma_div_long DK_PR((long l1, long l2)); /** Addition of 2 double values. @param d1 Value 1. @param d2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Summary. */ EXTERN double dkma_add_double_ok DK_PR((double d1, double d2, int *ok)); /** Subtraction of 2 double values. @param d1 Value 1. @param d2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Difference. */ EXTERN double dkma_sub_double_ok DK_PR((double d1, double d2, int *ok)); /** Multiplication of 2 double values. @param d1 Value 1. @param d2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Product. */ EXTERN double dkma_mul_double_ok DK_PR((double d1, double d2, int *ok)); /** Division of 2 double values. @param d1 Value 1. @param d2 Value 2. @param ok Pointer to variable to receive the error code (if any). @return Result. */ EXTERN double dkma_div_double_ok DK_PR((double d1, double d2, int *ok)); /** Addition of 2 double values. @param d1 Value 1. @param d2 Value 2. @return The summary. */ EXTERN double dkma_add_double DK_PR((double d1, double d2)); /** Substraction of 2 double values. @param d1 Value 1. @param d2 Value 2. @return The difference. */ EXTERN double dkma_sub_double DK_PR((double d1, double d2)); /** Multiplication of 2 double values. @param d1 Factor 1. @param d2 Factor 2. @return The product. */ EXTERN double dkma_mul_double DK_PR((double d1, double d2)); /** Division of 2 double values. @param d1 Dividend. @param d2 Divisor. @return The division result. */ EXTERN double dkma_div_double DK_PR((double d1, double d2)); /** Convert unsigned long to double, save errors. @param ul The unsigned long value. @param ok Pointer to a variable to receive the error code. @return The conversion result. */ EXTERN double dkma_ul_to_double_ok DK_PR((unsigned long ul, int *ok)); /** Convert unsigned long long to double, save errors. @param ul The unsigned long long value. @param ok Pointer to a variable to receive the error code. @return The conversion result. */ EXTERN double dkma_ull_to_double_ok DK_PR((dk_long_long_unsigned_t ul, int *ok)); /** Convert unsigned long to double. */ EXTERN double dkma_ul_to_double DK_PR((unsigned long ul)); /** Convert unsigned long to double @param ul The unsigned long value. @return The conversion result. */ EXTERN double dkma_ull_to_double DK_PR((dk_long_long_unsigned_t ul)); /** Convert long to double, save errors. @param l The long value. @param ok Pointer to a variable to receive the error code. @return The conversion result. */ EXTERN double dkma_l_to_double_ok DK_PR((long l, int *ok)); /** Convert long to double. @param l The long value. @return The conversion result. */ EXTERN double dkma_l_to_double DK_PR((long l)); /** Convert double to unsigned long, save range overflow errors. @param d The double value. @param ok Pointer to variable to receive the error code. @return The conversion result. */ EXTERN unsigned long dkma_double_to_ul_ok DK_PR((double d, int *ok)); /** Convert double to unsigned long. @param d The double value. @return The conversion result. */ EXTERN unsigned long dkma_double_to_ul DK_PR((double d)); /** Convert double to long, save range overflow errors. @param d The double value. @param ok Pointer to a variable to receive the error code. @return The conversion result. */ EXTERN long dkma_double_to_l_ok DK_PR((double d, int *ok)); /** Convert double to long. @param d The double value. @return The conversion result. */ EXTERN long dkma_double_to_l DK_PR((double d)); /** Restrict number of digits after decimal dot. @param x Original value. @param d Number of digits after decimal dot. @return The result. */ EXTERN double dkma_double_restrict_digits DK_PR((double x, unsigned d)); /** Restrict number of digits after decimal dot, enforce downward rounding. @param x Original value. @param d Number of digits after decimal dot. @return The result. */ EXTERN double dkma_double_restrict_downwards DK_PR((double x, unsigned d)); /** Add 2 long long unsigned values, save range check result. @param o1 First value. @param o2 Second value. @param ok Pointer to variable receiving error code if any. @return Summary of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_add_ull_ok DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2, int *ok)); /** Add 2 long long unsigned values. @param o1 First value. @param o2 Second value. @return Summary of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_add_ull DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2)); /** Substract 2 long long unsigned values, save range check result. @param o1 First value. @param o2 Second value. @param ok Pointer to variable receiving error code if any. @return Difference of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_sub_ull_ok DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2, int *ok)); /** Substract 2 long long unsigned values. @param o1 First value. @param o2 Second value. @return Difference of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_sub_ull DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2)); /** Multiplicate 2 long long unsigned values, save range check result. @param o1 First value. @param o2 Second value. @param ok Pointer to variable receiving error code if any. @return Product of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_mul_ull_ok DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2, int *ok)); /** Multiplicate 2 long long unsigned values. @param o1 First value. @param o2 Second value. @return Product of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_mul_ull DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2)); /** Divide 2 long long unsigned values, save range check result. @param o1 First value. @param o2 Second value. @param ok Pointer to variable receiving error code if any. @return Fraction of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_div_ull_ok DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2, int *ok)); /** Divide 2 long long unsigned values. @param o1 First value. @param o2 Second value. @return Fraction of \a o1 and \a o2. */ EXTERN dk_long_long_unsigned_t dkma_div_ull DK_PR((dk_long_long_unsigned_t o1, dk_long_long_unsigned_t o2)); /** Round to nearest integer. This is a fallback function for systems having no rint() function. @param d Original number. @return Number rounded to nearest integer. */ EXTERN double dkma_rint DK_PR((double d)); /** Calculate atan2(x,y)=atan(y/x). This is a fallback for systems having no atan2() function. @param y Height of the point. @param x Width of a point. @return Angle between x-axis an line from (0,0) to the point in radians. */ EXTERN double dkma_atan2 DK_PR((double y, double x)); /** Find greatest common divisor for two numbers. @param l1 First operand. @param l2 Second operand. @return Greatest common divisor. */ EXTERN dk_long_long_unsigned_t dkma_ull_gcd DK_PR((dk_long_long_unsigned_t l1, dk_long_long_unsigned_t l2)); /** Calculate least common multiple of two numbers, check for out-of-range result. @param u1 Operand 1. @param u2 Operand 2. @param ec Pointer to variable to receive error code. @return Least common multiple. */ EXTERN dk_long_long_unsigned_t dkma_ull_lcm_ok DK_PR((dk_long_long_unsigned_t u1, dk_long_long_unsigned_t u2, int *ec)); /** Calculate least common multiple of two numbers. @param l1 Operand 1. @param l2 Operand 2. @return Least common multiple. */ EXTERN dk_long_long_unsigned_t dkma_ull_lcm DK_PR((dk_long_long_unsigned_t l1, dk_long_long_unsigned_t l2)); /** Find greatest common divisor for two numbers. @param l1 First operand. @param l2 Second operand. @return Greatest common divisor. */ EXTERN unsigned long dkma_ul_gcd DK_PR((unsigned long l1, unsigned long l2)); /** Calculate least common multiple of two numbers, check for out-of-range result. @param l1 Operand 1. @param l2 Operand 2. @param ec Pointer to variable to receive error code. @return Least common multiple. */ EXTERN unsigned long dkma_ul_lcm_ok DK_PR((unsigned long l1, unsigned long l2, int *ec)); /** Calculate least common multiple of two numbers. @param l1 Operand 1. @param l2 Operand 2. @return Least common multiple. */ EXTERN unsigned long dkma_ul_lcm DK_PR((unsigned long l1, unsigned long l2)); /** Find greatest common divisor for two numbers. @param l1 First operand. @param l2 Second operand. @return Greatest common divisor. */ EXTERN long dkma_l_gcd DK_PR((long l1, long l2)); /** Calculate least common multiple of two numbers, check for out-of-range result. @param l1 Operand 1. @param l2 Operand 2. @param ec Pointer to variable to receive error code. @return Least common multiple. */ EXTERN long dkma_l_lcm_ok DK_PR((long l1, long l2, int *ec)); /** Calculate least common multiple of two numbers. @param l1 Operand 1. @param l2 Operand 2. @return Least common multiple. */ EXTERN long dkma_l_lcm DK_PR((long l1, long l2)); /** Print double to file, avoid exponential notation. @param f File to print to. @param d Value to print. */ EXTERN void dkma_fputs_double_no_exp DK_PR((FILE *f, double d)); /** Print double from text to file, avoid exponent notation. This function is called by dkma_fputs_double_no_exp(), it is not intended for direct use. @param f File to print to. @param s String containing the floating point number. */ EXTERN void dkma_fputs_double_str_no_exp DK_PR((FILE *f, char *s)); #if defined(__cplusplus) } #endif /* Yes, there are systems without M_PI or M_PI_2 in math.h */ #ifndef M_PI /** Define pi if not already defined in math.h */ #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 /** Define 0.5 * pi if not already defined in math.h */ #define M_PI_2 1.57079632679489661923 #endif #endif