-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Expand file tree
/
Copy pathlnum.h
More file actions
119 lines (103 loc) · 4.1 KB
/
lnum.h
File metadata and controls
119 lines (103 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
** $Id: lnum.h,v ... $
** Internal Number model
** See Copyright Notice in lua.h
*/
#ifndef lnum_h
#define lnum_h
#include <math.h>
#include "lobject.h"
/*
** The luai_num* macros define the primitive operations over 'lua_Number's
** (not 'lua_Integer's, not 'lua_Complex').
*/
#define luai_numadd(a,b) ((a)+(b))
#define luai_numsub(a,b) ((a)-(b))
#define luai_nummul(a,b) ((a)*(b))
#define luai_numdiv(a,b) ((a)/(b))
#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
#define luai_numpow(a,b) (_LF(pow)(a,b))
#define luai_numunm(a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
/*
* If '-ffast-math' is used, there are no NaNs or Infs. We shouldn't pretend
* there is.
*/
#ifdef __FAST_MATH__
# define luai_numisnan(a) (0) /* has no concept of NANs */
#elif (defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define luai_numisnan(a) isnan(a) /* same regardless of number size */
#else
# define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
#ifdef LUA_TINT
int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
int try_unmint( lua_Integer *r, lua_Integer ib );
#endif
#ifdef LNUM_COMPLEX
static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
/*
* Complex power
*
* C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
* -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
*
* [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
* = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
* r = sqrt(a^2+b^2), t = arctan( b/a )
*
* Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
* Could also be calculated using: x^y = exp(ln(x)*y)
*
* Note: Defined here (and not in .c) so 'lmathlib.c' can share the
* implementation.
*/
static inline
lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
{
lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
if (ai==0 && bi==0) { /* a^c (real) */
return luai_numpow( ar, br );
}
int br_int= (int)br;
if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
/* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
*/
lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
lua_Number cos_z, sin_z;
/* Situation depends upon c (N) in the following manner:
*
* N%4==0 => cos(c*t)=1, sin(c*t)=0
* (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
* N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
* (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
*/
int br_int_abs = br_int<0 ? -br_int:br_int;
switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
case 0: cos_z=1, sin_z=0; break;
case 2: case -2: cos_z=-1, sin_z=0; break;
case 1: case -3: cos_z=0, sin_z=1; break;
case 3: case -1: cos_z=0, sin_z=-1; break;
default: lua_assert(0); return 0;
}
return k*cos_z + (k*sin_z)*I;
}
return _LF(cpow) ( a, b );
}
#endif
LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
#endif