chiark / gitweb /
more robustness to underflow etc. (fix #36)
[nlopt.git] / api / general.c
1 /* Copyright (c) 2007-2014 Massachusetts Institute of Technology
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  * 
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  * 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
21  */
22
23 #include <math.h>
24 #include <float.h>
25
26 #include "nlopt-internal.h"
27
28 /*************************************************************************/
29
30 int nlopt_isinf(double x) {
31      return fabs(x) >= HUGE_VAL * 0.99
32 #ifdef HAVE_ISINF
33           || isinf(x)
34 #endif
35           ;
36 }
37
38 int nlopt_isfinite(double x) {
39     return fabs(x) <= DBL_MAX;
40 }
41
42 int nlopt_istiny(double x)
43 {
44 #if defined(HAVE_FPCLASSIFY)
45     return x == 0.0 || fpclassify(x) == FP_SUBNORMAL;
46 #elif defined(_WIN32)
47     if (x == 0.0)
48         return 1;
49     else {
50         int c = _fpclass(x);
51         return c == _FPCLASS_ND || c == _FPCLASS_PD;
52     }
53 #else
54     return fabs(x) < 2.2250738585072014e-308; /* assume IEEE 754 double */
55 #endif
56 }
57
58 int nlopt_isnan(double x)
59 {
60 #if defined(HAVE_ISNAN)
61     return isnan(x);
62 #elif defined(_WIN32)
63     return _isnan(x);
64 #else
65     return x != x; /* might fail with aggressive optimization */
66 #endif
67 }
68
69 /*************************************************************************/
70
71 void NLOPT_STDCALL nlopt_version(int *major, int *minor, int *bugfix)
72 {
73      *major = MAJOR_VERSION;
74      *minor = MINOR_VERSION;
75      *bugfix = BUGFIX_VERSION;
76 }
77
78 /*************************************************************************/
79
80 static const char nlopt_algorithm_names[NLOPT_NUM_ALGORITHMS][256] = {
81      "DIRECT (global, no-derivative)",
82      "DIRECT-L (global, no-derivative)",
83      "Randomized DIRECT-L (global, no-derivative)",
84      "Unscaled DIRECT (global, no-derivative)",
85      "Unscaled DIRECT-L (global, no-derivative)",
86      "Unscaled Randomized DIRECT-L (global, no-derivative)",
87      "Original DIRECT version (global, no-derivative)",
88      "Original DIRECT-L version (global, no-derivative)",
89 #ifdef WITH_CXX
90      "StoGO (global, derivative-based)",
91      "StoGO with randomized search (global, derivative-based)",
92 #else
93      "StoGO (NOT COMPILED)",
94      "StoGO randomized (NOT COMPILED)",
95 #endif
96      "original L-BFGS code by Nocedal et al. (NOT COMPILED)",
97      "Limited-memory BFGS (L-BFGS) (local, derivative-based)",
98      "Principal-axis, praxis (local, no-derivative)",
99      "Limited-memory variable-metric, rank 1 (local, derivative-based)",
100      "Limited-memory variable-metric, rank 2 (local, derivative-based)",
101      "Truncated Newton (local, derivative-based)",
102      "Truncated Newton with restarting (local, derivative-based)",
103      "Preconditioned truncated Newton (local, derivative-based)",
104      "Preconditioned truncated Newton with restarting (local, derivative-based)",
105      "Controlled random search (CRS2) with local mutation (global, no-derivative)",
106      "Multi-level single-linkage (MLSL), random (global, no-derivative)",
107      "Multi-level single-linkage (MLSL), random (global, derivative)",
108      "Multi-level single-linkage (MLSL), quasi-random (global, no-derivative)",
109      "Multi-level single-linkage (MLSL), quasi-random (global, derivative)",
110      "Method of Moving Asymptotes (MMA) (local, derivative)",
111      "COBYLA (Constrained Optimization BY Linear Approximations) (local, no-derivative)",
112      "NEWUOA unconstrained optimization via quadratic models (local, no-derivative)",
113      "Bound-constrained optimization via NEWUOA-based quadratic models (local, no-derivative)",
114      "Nelder-Mead simplex algorithm (local, no-derivative)",
115      "Sbplx variant of Nelder-Mead (re-implementation of Rowan's Subplex) (local, no-derivative)",
116      "Augmented Lagrangian method (local, no-derivative)",
117      "Augmented Lagrangian method (local, derivative)",
118      "Augmented Lagrangian method for equality constraints (local, no-derivative)",
119      "Augmented Lagrangian method for equality constraints (local, derivative)",
120      "BOBYQA bound-constrained optimization via quadratic models (local, no-derivative)",
121      "ISRES evolutionary constrained optimization (global, no-derivative)",
122      "Augmented Lagrangian method (needs sub-algorithm)",
123      "Augmented Lagrangian method for equality constraints (needs sub-algorithm)",
124      "Multi-level single-linkage (MLSL), random (global, needs sub-algorithm)",
125      "Multi-level single-linkage (MLSL), quasi-random (global, needs sub-algorithm)",
126      "Sequential Quadratic Programming (SQP) (local, derivative)",
127      "CCSA (Conservative Convex Separable Approximations) with simple quadratic approximations (local, derivative)",
128      "ESCH evolutionary strategy"
129 };
130
131 const char * NLOPT_STDCALL nlopt_algorithm_name(nlopt_algorithm a)
132 {
133      if (((int) a) < 0 || a >= NLOPT_NUM_ALGORITHMS) return "UNKNOWN";
134      return nlopt_algorithm_names[a];
135 }
136
137 /*************************************************************************/
138 /* get thread id, if possible, for use in nlopt_srand_time to ensure that
139    different threads have a different default seed even if they are called
140    simultaneously */
141
142 #if defined(_WIN32) || defined(__WIN32__)
143 #  include <windows.h>
144 #  define my_gettid GetCurrentThreadId
145 #elif defined(HAVE_GETTID_SYSCALL)
146 #  include <unistd.h>
147 #  include <sys/syscall.h>
148 #  define my_gettid() syscall(SYS_gettid)
149 #elif defined(HAVE_GETPID)
150 #  include <sys/types.h>
151 #  include <unistd.h>
152 #  define my_gettid getpid
153 #else
154 #  define my_gettid() (0)
155 #endif
156
157 /*************************************************************************/
158
159 static THREADLOCAL int nlopt_srand_called = 0;
160 void NLOPT_STDCALL nlopt_srand(unsigned long seed) {
161      nlopt_srand_called = 1;
162      nlopt_init_genrand(seed);
163 }
164
165 void NLOPT_STDCALL nlopt_srand_time(void) {
166      nlopt_srand(nlopt_time_seed() + my_gettid() * 314159);
167 }
168
169 void nlopt_srand_time_default(void) {
170      if (!nlopt_srand_called) nlopt_srand_time();
171 }
172
173 /*************************************************************************/