Sun position
Sun position algorithm
instead-of-math.h
Go to the documentation of this file.
1 #ifndef INSTEAD_OF_MATH_H
2 #define INSTEAD_OF_MATH_H
3 /*============================================================================*/
4 /*!\file
5  * \brief instead-of-math.h - header to be included instead of math.h
6  *
7  * \author David Hoadley <vcrumble@westnet.com.au>
8  *
9  * \details
10  * This header needs to be included instead of the standard C library
11  * header math.h, in order to provide some routines that are missing
12  * or possibly missing from math.h. This header will include math.h
13  * for you.
14  *
15  * The reason it must be included instead of math.h is a little
16  * obscure. One of the routines we want is the sincos() routine. Two
17  * versions of math.h actually do have it: The GNU C library does, and
18  * the Apple Clang library also has it, but under a different name.
19  *
20  * The problem is, to gain access to the function, we need to include
21  * the appropriate incantation BEFORE including math.h if we are using
22  * the GNU C library, but we need to add definitions AFTER including
23  * math.h if we are using the Apple Clang library.
24  *
25  * So use this header instead of math.h to look after this problem.
26  *
27  * This header also provides the following missing function:
28  * - normalize()
29  * A proper modulo function. Unlike fmod(), result is
30  * always positive. Used to to normalize a cyclic variable
31  * to a range, e.g. an angle in radian to the range
32  * [0, 2Pi), or an angle in degrees to the range [0, 360.0)
33  *
34  *
35  * \copyright
36  * \parblock
37  * Copyright (c) 2020, David Hoadley <vcrumble@westnet.com.au>
38  * All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions are met:
42  *
43  * * Redistributions of source code must retain the above copyright notice, this
44  * list of conditions and the following disclaimer.
45  * * Redistributions in binary form must reproduce the above copyright notice,
46  * this list of conditions and the following disclaimer in the documentation
47  * and/or other materials provided with the distribution.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
50  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
53  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59  * POSSIBILITY OF SUCH DAMAGE.
60  * \endparblock
61  *
62  *==============================================================================
63  */
64 #include "general.h" /* Is this a C99 or later compiler? */
65 
66 /*
67  * Global #defines and typedefs
68  */
69 
70 
71 /*
72  * Global functions available to be called by other modules
73  */
74 #ifdef __cplusplus
75 extern "C" {
76 #endif
77 
78 /* -------------- The possible missing sincos() function -------------- */
79 /*! Calculates sine and cosine of an angle. Where the math library supports it,
80  this is more efficient than calling \c sin() and \c cos() separately.
81  \param[in] angle_rad Angle whose sine and cosine is wanted (radian)
82  \param[out] sinA sine of angle \a angle_rad
83  \param[out] cosA cosine of angle \a angle_rad
84 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
85 #if defined(__APPLE__)
86  /* This is the CLANG compiler on an Apple computer (probably a mac). There
87  is a sincos() function available, but it is called __sincos() instead.
88  Re-direct all calls to sincos() to use __sincos() instead. */
89 # include <math.h> /* Must be done before defining fn below */
90 # if defined (PREDEF_STANDARD_C_1999)
91  /* Compiler supports inline functions */
92  static inline void sincos(double angle_rad, double *sinA, double *cosA)
93  {
94  __sincos(angle_rad, sinA, cosA);
95  }
96 # else
97  /* C89/C90 compiler - no inline functions. Need macros instead */
98  #define sincos(angle_rad_, sinA_, cosA_) __sincos(angle_rad_, sinA_, cosA_)
99 # endif
100 
101 #elif defined(__GNUC__)
102  /* This is the GNU C compiler. There is a sincos() function available in
103  the GNU C library, but it is only accessible if the following macro is
104  defined BEFORE including <math.h>. So do it here. */
105 # define _GNU_SOURCE
106 # include <math.h>
107 
108 #else
109  /* No sincos() function available. Oh well. Get sine and cosine separately.
110  This is less efficient than a true sincos(), but at least it will work.*/
111 # include <math.h>
112 # if defined (PREDEF_STANDARD_C_1999)
113  /* Compiler supports inline functions */
114  static inline void sincos(double angle_rad, double *sinA, double *cosA)
115  {
116  *sinA = sin(angle_rad);
117  *cosA = cos(angle_rad);
118  }
119 # else
120  /* C89/C90 compiler - no inline functions. Need macros instead */
121  #define sincos(angle_rad_, sinA_, cosA_) \
122  { *sinA_ = sin(angle_rad_); \
123  *cosA_ = cos(angle_rad_); }
124 # endif
125 #endif
126 
127 
128 /* -------------- The definitely missing normalize() function -------------- */
129 
130 /*! Normalizes a cyclic double precision floating point variable \a x
131  to the interval [0, range), assuming \a range is > 0. (If \a range is
132  negative, this will normalize \a x to the interval (range, 0], but this is
133  not the main use case for this function.)
134  \returns The value of \a x, within the range [0, range)
135  \param[in] x The variable (e.g. an angle in degrees or radian)
136  \param[in] range The range to normalize \a x to (e.g. 2Pi or 360.0). It must
137  be non-zero.
138 
139  This function returns the same results as \c fmod() for positive \a x and
140  \a range. Where it differs is in its handling of negative values of \a x.
141 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
142 #if defined (PREDEF_STANDARD_C_1999)
143 /* Compiler supports inline functions */
144 static inline double normalize(double x, double range)
145 {
146  return x - floor(x / range) * range;
147 }
148 #else
149  /* C89/C90 compiler - no inline functions. Need macros instead */
150  #define normalize(x__, range__) ((x__) - floor((x__) / (range__)) * (range__))
151 #endif
152 
153 
154 /*
155  * Global variables accessible by other modules
156  */
157 
158 
159 #ifdef __cplusplus
160 }
161 #endif
162 
163 #endif /* INSTEAD_OF_MATH_H */
164 
general.h
general.h - definitions of general use to (standard) C programs
sincos
static void sincos(double angle_rad, double *sinA, double *cosA)
Calculates sine and cosine of an angle.
Definition: instead-of-math.h:114
normalize
static double normalize(double x, double range)
Normalizes a cyclic double precision floating point variable x to the interval [0,...
Definition: instead-of-math.h:144