00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00045
#ifndef pl_math_INC
00046
#define pl_math_INC
00047
00048
#include <cmath>
00049
#include <cfloat>
00050
#include <climits>
00051
#include <plearn/base/plerror.h>
00052
00053
namespace PLearn {
00054
using namespace std;
00055
00056
#ifdef USEDOUBLE
00057
#define real double
00058
#endif
00059
00060
#ifdef USEFLOAT
00061
#define real float
00062
#endif
00063
00064
00065
#ifdef USEFLOAT
00066
#define REAL_MAX FLT_MAX
00067
#else
00068 #define REAL_MAX DBL_MAX
00069
#endif
00070
00071 union _plearn_nan_type {
unsigned char c[4];
float d; };
00072 extern _plearn_nan_type plearn_nan;
00073
00075 #define MISSING_VALUE (plearn_nan.d)
00076
00077
using namespace std;
00078
00079
using std::log;
00080
using std::sqrt;
00081
using std::pow;
00082
using std::exp;
00083
using std::tanh;
00084
using std::abs;
00085
00087 #define MIN(a,b) ((a)<(b)?(a):(b))
00088 #define MAX(a,b) ((a)>(b)?(a):(b))
00089
00090 #define SIGN(a) ((a)>=0?1:-1)
00091
00092 inline real sign(
real a) {
00093
if (a>0)
return 1;
00094
if (a<0)
return -1;
00095
return 0;
00096 }
00097 inline real positive(
real a) {
if (a>0)
return a;
return 0; }
00098 inline real negative(
real a) {
if (a<0)
return a;
return 0; }
00099
00100 #define ABS(x) ((x)>0 ?(x) :-(x))
00101 #define random() rand()
00102
00103 #define Pi 3.141592653589793
00104 #define Log2Pi 1.837877066409
00105 #define LOG_2 0.693147180559945
00106 #define LOG_INIT -FLT_MAX
00107 #define MINUS_LOG_THRESHOLD -18.42
00108
00109
#if defined(_MSC_VER) || defined(_MINGW_)
00112
#define drand48() ( rand()/ (double)(RAND_MAX+1) )
00113
00114
#define log1p(a) log((real)1.0+(real)a)
00115
#define rint(a) (int)(a+(real)0.5)
00116
#define isnan(x) _isnan(x)
00117
#define finite(x) _finite(x)
00118
#endif
00119
00120
#if defined(DARWIN)
00121
#define isnan(x) __isnan(x)
00122
#endif
00123
00124
template<
class T>
00125 inline T
square(
const T& x)
00126 {
return x*
x; }
00127
00128
00129
00130
00131
real square_f(
real x);
00132
00133
template<
class T>
00134 inline T
two(
const T& x)
00135 {
return x+
x; }
00136
00137 #define TANHTABLESIZE 5000
00138 #define MAXTANHX 10.
00139
00140 class PLMathInitializer
00141 {
00142
public:
00143
PLMathInitializer();
00144
~PLMathInitializer();
00145 };
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
#if defined(LINUX) && !defined(__INTEL_COMPILER) // note: intel compiler on SGI does not like that
00158
#define DOUBLE_TO_INT(in,out) __asm__ __volatile__ ("fistpl %0" : "=m" (out) : "t" (in) : "st")
00159
#else
00160 #define DOUBLE_TO_INT(in, out) out = int(in)
00161
#endif
00162
00163
extern float tanhtable[
TANHTABLESIZE];
00164
extern PLMathInitializer pl_math_initializer;
00165
00166 inline real fasttanh(
const real& x)
00167 {
00168
if(
x>0)
00169 {
00170
if(
x>
MAXTANHX)
00171
return real(
tanhtable[
TANHTABLESIZE-1]);
00172
else
00173 {
00174
int i;
00175
DOUBLE_TO_INT(
double(
x*((
TANHTABLESIZE-1)/
MAXTANHX)), i);
00176
return real(
tanhtable[i]);
00177 }
00178 }
00179
else
00180 {
00181
real nx = -
x;
00182
if(nx>
MAXTANHX)
00183
return real(-
tanhtable[
TANHTABLESIZE-1]);
00184
else
00185 {
00186
int i;
00187
DOUBLE_TO_INT(
double(nx*((
TANHTABLESIZE-1)/
MAXTANHX)), i);
00188
return real(-
tanhtable[i]);
00189 }
00190 }
00191 }
00192
00193 inline real fastsigmoid(
const real& x)
00194 {
return (
real)0.5*(
fasttanh(0.5*
x)+1.); }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 inline real ultrafasttanh(
const real& x)
00213 {
00214
if(
x>=0)
00215
return (
x<1.7 ? (1.5*
x/(1+
x)) : (
x<3 ? (0.935409070603099 + 0.0458812946797165*(
x-1.7)) :0.99505475368673));
00216
else
00217 {
00218
real xx = -
x;
00219
return -(xx<1.7 ? (1.5*xx/(1+xx)) : ( xx<3 ? (0.935409070603099 + 0.0458812946797165*(xx-1.7)) :0.99505475368673));
00220 }
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 inline real ultrafastsigmoid(
const real& x)
00231 {
00232
00233
return (
real)0.5*(
ultrafasttanh(0.5*
x)+1.);
00234
00235 }
00236
00239
template<
class T>
00240 inline bool is_missing(
const T& x) {
return false; }
00241
00243 inline bool is_missing(
double x) {
return isnan(
x)!=0; }
00244
00246 inline bool is_missing(
float x) {
return isnan(
x)!=0; }
00247
00248 inline bool is_integer(
real x) {
return real(
int(
x))==
x; }
00249
00250 inline real FABS(
real x)
00251 {
return x>=0. ?
x :-
x; }
00252
00253 #define FSWAP(a,b) do {real _c; _c = *(a); *(a) = *(b); *(b) = _c;} while(0)
00254 #define FLOAT_THRESHOLD 0.00001
00255 #define FEQUAL(a,b) (FABS((a)-(b))<FLOAT_THRESHOLD)
00256
00257
00258 inline real mypow(
real x,
real p)
00259 {
return x==0 ?0 :
pow(
x,p); }
00260
00261 inline real ipow(
real x,
int p)
00262 {
00263
real result = 1.0;
00264
while(p--)
00265 result *=
x;
00266
return result;
00267 }
00268
00270 inline real sigmoid(
real x)
00271 {
return (
real)0.5*(
tanh(0.5*
x)+1.); }
00272
00275 inline real is_positive(
real x) {
return x>0? 1 : 0; }
00276
00278 inline real inverse_sigmoid(
real x)
00279 {
00280
#ifdef BOUNDCHECK
00281
if (
x < 0. ||
x > 1.)
00282
PLERROR(
"In inv_sigmoid_value: a should be in [0,1]");
00283
#endif
00284
if (
FEQUAL(
x,0.))
00285
return -88.;
00286
else if (
FEQUAL(
x,1.))
00287
return 14.5;
00288
else
00289
return real(-
log(1./
x - 1.));
00290 }
00291
00293 inline real softplus(
real x)
00294 {
00295
if(
x<=-30.)
00296
return 0.0;
00297
else if(
x>=30.)
00298
return x;
00299
else
00300
return log1p(
exp(
x));
00302 }
00303
00304 inline real tabulated_softplus(
real x)
00305 {
00306
static const int n_softplus_values = 1000000;
00307
static const real min_softplus_arg = -10;
00308
static const real max_softplus_arg = 10;
00309
static const real softplus_delta = (n_softplus_values-1)/(max_softplus_arg-min_softplus_arg);
00310
static real softplus_values[n_softplus_values];
00311
static bool computed_softplus_table =
false;
00312
if (!computed_softplus_table)
00313 {
00314
real y=min_softplus_arg;
00315
real dy=1.0/softplus_delta;
00316
for (
int i=0;i<n_softplus_values;i++,y+=dy)
00317 softplus_values[i] =
softplus(y);
00318 computed_softplus_table=
true;
00319 }
00320
if (
x<min_softplus_arg)
return 0;
00321
if (
x>max_softplus_arg)
return x;
00322
int bin =
int(rint((
x-min_softplus_arg)*softplus_delta));
00323
return softplus_values[bin];
00324 }
00325
00327 inline real inverse_softplus(
real y)
00328 {
00329
if (y<0)
00330
return MISSING_VALUE;
00331
if (y>=30)
00332
return y;
00333
if (y==0)
00334
return -30;
00335
return log(
exp(y)-1);
00336 }
00337
00338 inline real hard_slope(
real x,
real left=0,
real right=1)
00339 {
00340
if (
x<
left)
return 0;
00341
if (
x>
right)
return 1;
00342
return (
x-
left)/(
right-
left);
00343 }
00344
00345
00346
00347
00348
00349 inline real soft_slope(
real x,
real smoothness=1,
real left=0,
real right=1)
00350 {
00351
if (smoothness==0)
00352
return 0.5;
00353
if (smoothness>1000)
00354
return hard_slope(
x,
left,
right);
00355
return 1 + (
softplus(-smoothness*(
x-
left))-
softplus(-smoothness*(
x-
right)))/(smoothness*(
right-
left));
00356 }
00357
00358 inline real tabulated_soft_slope(
real x,
real smoothness=1,
real left=0,
real right=1)
00359 {
00360
if (smoothness==0)
00361
return 0.5;
00362
if (smoothness>1000)
00363
return hard_slope(
x,
left,
right);
00364
return 1 + (
tabulated_softplus(-smoothness*(
x-
left))-
tabulated_softplus(-smoothness*(
x-
right)))/(smoothness*(
right-
left));
00365 }
00366
00367
00368 inline real d_soft_slope(
real x,
real smoothness=1,
real left=0,
real right=1)
00369 {
00370
00371
return (-
sigmoid(-smoothness*(
x-
left))+
sigmoid(-smoothness*(
x-
right)))/(
right-
left);
00372 }
00373
00375 inline int n_choose(
int M,
int N)
00376 {
00377
int k=M-N;
00378
float res=1;
00379
int i;
00380
for (i=1;i<=
k;i++) {
00381 res *= (i+N)/(
float)i;
00382 }
00383
return (
int)(res+0.499);
00384 }
00385
00386
real safeflog(
real a);
00387
real safeexp(
real a);
00388
00389
real log(
real base,
real a);
00390
real logtwo(
real a);
00391
real safeflog(
real base,
real a);
00392
real safeflog2(
real a);
00393
00394 typedef real (*
tRealFunc)(
real);
00395 typedef real (*
tRealReadFunc)(
real,
real);
00396
00398
real logadd(
real log_a,
real log_b);
00399
00401
real logsub(
real log_a,
real log_b);
00402
00407
real dilogarithm(
real x);
00408
00409 inline real softplus_primitive(
real x) {
00410
return -
dilogarithm(-
exp(
x));
00411 }
00412
00413 inline real tabulated_softplus_primitive(
real x) {
00414
static const int n_softplus_primitive_values = 10000;
00415
static const real min_softplus_primitive_arg = -20;
00416
static const real max_softplus_primitive_arg = 10;
00417
static const real max_offset = max_softplus_primitive_arg*max_softplus_primitive_arg*0.5;
00418
static const real softplus_primitive_delta = (n_softplus_primitive_values-1)/(max_softplus_primitive_arg-min_softplus_primitive_arg);
00419
static real softplus_primitive_values[n_softplus_primitive_values];
00420
static bool computed_softplus_primitive_table =
false;
00421
if (!computed_softplus_primitive_table)
00422 {
00423
real y=min_softplus_primitive_arg;
00424
real dy=1.0/softplus_primitive_delta;
00425
for (
int i=0;i<n_softplus_primitive_values;i++,y+=dy)
00426 softplus_primitive_values[i] =
softplus_primitive(y);
00427 computed_softplus_primitive_table=
true;
00428 }
00429
if (
x<min_softplus_primitive_arg)
return 0;
00430
if (
x>max_softplus_primitive_arg)
return softplus_primitive_values[n_softplus_primitive_values-1]+
x*
x*0.5 - max_offset;
00431
int bin =
int(rint((
x-min_softplus_primitive_arg)*softplus_primitive_delta));
00432
return softplus_primitive_values[bin];
00433 }
00434
00435
real hard_slope_integral(
real left=0,
real right=1,
real a=0,
real b=1);
00436
00437
00438
00439
real soft_slope_integral(
real smoothness=1,
real left=0,
real right=1,
real a=0,
real b=1);
00440
real tabulated_soft_slope_integral(
real smoothness=1,
real left=0,
real right=1,
real a=0,
real b=1);
00441
00442 }
00443
00444
00445
#endif