aboutsummaryrefslogtreecommitdiff
path: root/Client/ThirdParty/math-sll/math-sll.h
blob: f972de53fabf3b917c5f6b4d1cfabfee10f95409 (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
#if !defined(MATH_SLL_H)
#  define MATH_SLL_H

namespace MathSLL {

/*
 * Revision v1.24
 *
 *	A fixed point (32.32 bit) math library.
 *
 * Description
 *
 *	Floating point packs the most accuracy in the available bits, but it
 *	often provides more accuracy than is required.  It is time consuming to
 *	carry the extra precision around, particularly on platforms that don't
 *	have a dedicated floating point processor.
 *
 *	This library is a compromise.  All math is done using the 64 bit signed
 *	"long long" format (sll), and is not intended to be portable, just as
 *	simple and as fast as possible.
 *
 *	As some processors lack division instructions but have multiplication
 *	instructions, multiplication is favored over division.  This can be a
 *	penalty when used on a processor with a division instruction, so it is
 *	recommended to modify the division functions and macros in that case.
 *
 *	On procesors without multiplication instructions, other algorithms, for
 *	example CORDIC, are probably faster.
 *
 *	Since "long long" is a elementary type, it can be passed around without
 *	resorting to the use of pointers.  Since the format used is fixed point,
 *	there is never a need to do time consuming checks and adjustments to
 *	maintain normalized numbers, as is the case in floating point.
 *
 *	Simply put, this library is limited to handling numbers with a whole
 *	part of up to 2^31 - 1 = 2.147483647e9 in magnitude, and fractional
 *	parts down to 2^-32 = 2.3283064365e-10 in magnitude.  This yields a
 *	decent range and accuracy for many applications.
 *
 * IMPORTANT
 *
 *	No checking for arguments out of range (error).
 *	No checking for divide by zero (error).
 *	No checking for overflow (error).
 *	No checking for underflow (warning).
 *	Chops, doesn't round.
 *
 * Functions
 *
 *	sll dbl2sll(double d)			double to sll
 *	double sll2dbl(sll s)			sll to double
 *
 *	sll int2sll(int i)			integer to sll
 *	int sll2int(sll s)			sll to integer
 *
 *	sll sllint(sll s)			Set fractional-part to 0
 *	sll sllfrac(sll s)			Set integer-part to 0
 *
 *	sll slladd(sll x, sll y)		x + y
 *	sll sllneg(sll x)			-x
 *	sll sllsub(sll x, sll y)		x - y
 *
 *	sll sllmul(sll x, sll y)		x * y
 *	sll sllmul2(sll x)			x * 2
 *	sll sllmul2n(sll x, int n)		x * 2^n, 0 <= n <= 31
 *	sll sllmul4(sll x)			x * 4
 *
 *	sll slldiv(sll x, sll y)		x / y
 *	sll slldiv2(sll x)			x / 2
 *	sll slldiv2n(sll x, int n)		x / 2^n, 0 <= n <= 31
 *	sll slldiv4(sll x)			x / 4
 *
 *	sll sllcos(sll x)			cos x
 *	sll sllsin(sll x)			sin x
 *	sll slltan(sll x)			tan x
 *
 *	sll sllsec(sll x)			sec x = 1 / cos x
 *	sll sllcsc(sll x)			csc x = 1 / sin x
 *	sll sllcot(sll x)			cot x = 1 / tan x = cos x / sin x
 *
 *	sll sllacos(sll x)			acos x
 *	sll sllasin(sll x)			asin x
 *	sll sllatan(sll x)			atan x
 *
 *	sll sllcosh(sll x)			cosh x
 *	sll sllsinh(sll x)			sinh x
 *	sll slltanh(sll x)			tanh x
 *
 *	sll sllsech(sll x)			sech x
 *	sll sllcsch(sll x)			cosh x
 *	sll sllcoth(sll x)			coth x
 *
 *	sll sllexp(sll x)			e^x
 *	sll slllog(sll x)			ln x
 *
 *	sll sllinv(sll v)			1 / x
 *	sll sllpow(sll x, sll y)		x^y
 *	sll sllsqrt(sll x)			x^(1 / 2)
 *
 *	sll sllfloor(sll x)			floor x
 *	sll sllceil(sll x)			ceiling x
 *
 * Macros
 *
 *	Use of the following macros is optional, but may be beneficial with
 *	some compilers.  Using the non-macro versions is strongly recommended.
 *
 *	WARNING:  macros do not type-check their arguments!
 *
 *	_int2sll(X)				See function int2sll()
 *	_sll2int(X)				See function sll2int()
 *
 *	_sllint(X)				See function sllint()
 *	_sllfrac(X)				See function sllfrac()
 *
 *	_slladd(X,Y)				See function slladd()
 *	_sllneg(X)				See function sllneg()
 *	_sllsub(X,Y)				See function sllsub()
 *
 *	_sllmul2(X)				See function sllmul2()
 *	_sllmul2n(X)				See function sllmul2n()
 *	_sllmul4(X)				See function sllmul4()
 *
 *	_slldiv(X,Y)				See function slldiv()
 *	_slldiv2(X,Y)				See function slldiv2()
 *	_slldiv2n(X,Y)				See function slldiv2n()
 *	_slldiv4(X,Y)				See function slldiv4()
 *
 * Credits
 *
 *	Maintained, conceived, written, and fiddled with by:
 *
 *		Andrew E. Mileski <andrewm@isoar.ca>
 *
 *	Other source code contributors:
 *
 *		Kevin Rockel
 *		Kevin Michael Woley
 *		Mark Anthony Lisher
 *		Nicolas Pitre
 *		Anonymous
 *
 * License
 *
 *	Licensed under the terms of the MIT license:
 *
 * Copyright (c) 2000,2002,2006,2012,2016 Andrew E. Mileski <andrewm@isoar.ca>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The copyright notice, and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/* DEC SA-110 "StrongARM" (armv4l) architecture has a big-endian double */
#if defined(__arm__)
#  if (!defined(__BYTE_ORDER__) || (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#	define BROKEN_IEEE754_DOUBLE
#  endif
#endif

#ifdef _MSC_VER
# define __inline__ __inline
# ifndef _MSC_STDINT_H_
typedef signed __int64       int64_t;
typedef unsigned __int64     uint64_t;
#endif
#define __extension__ 
#else 
#include <stdint.h>
#if defined(__GNUC__)
	
#else
	#define __inline__ inline
#endif
#endif
/*
 * Data types
 */

__extension__ typedef int64_t sll;
__extension__ typedef uint64_t ull;

/*
 * Function prototypes
 */

sll dbl2sll(double d);
double sll2dbl(sll s);

static __inline__ sll int2sll(int i);
static __inline__ int sll2int(sll s);

static __inline__ sll sllint(sll s);
static __inline__ sll sllfrac(sll s);

static __inline__ sll slladd(sll x, sll y);
static __inline__ sll sllneg(sll s);
static __inline__ sll sllsub(sll x, sll y);
sll sllmul(sll x, sll y);
static __inline__ sll sllmul2(sll x);
static __inline__ sll sllmul4(sll x);
static __inline__ sll sllmul2n(sll x, int n);

static __inline__ sll slldiv(sll x, sll y);
static __inline__ sll slldiv2(sll x);
static __inline__ sll slldiv4(sll x);
static __inline__ sll slldiv2n(sll x, int n);

sll sllcos(sll x);
sll sllsin(sll x);
sll slltan(sll x);

static __inline__ sll sllacos(sll x);
sll sllasin(sll x);
sll sllatan(sll x);

static __inline__ sll sllsec(sll x);
static __inline__ sll sllcsc(sll x);
static __inline__ sll sllcot(sll x);

static __inline__ sll sllcosh(sll x);
static __inline__ sll sllsinh(sll x);
static __inline__ sll slltanh(sll x);

static __inline__ sll sllsech(sll x);
static __inline__ sll sllcsch(sll x);
static __inline__ sll sllcoth(sll x);

sll sllexp(sll x);
sll slllog(sll x);

sll sllpow(sll x, sll y);
sll sllinv(sll v);
sll sllsqrt(sll x);
sll slld2dsqrt(sll x);

static __inline__ sll sllfloor(sll x);
static __inline__ sll sllceil(sll x);

/*
 * Macros
 *
 * WARNING - Macros don't type-check!
 */

#define _int2sll(X)	(((sll) (X)) << 32)
#define _sll2int(X)	((int) ((X) >> 32))

#define _sllint(X)	((X) & 0xffffffff00000000LL)
#define _sllfrac(X)	((X) & 0x00000000ffffffffLL)

#define _slladd(X,Y)	((X) + (Y))
#define _sllneg(X)	(-(X))
#define _sllsub(X,Y)	((X) - (Y))

#define _sllmul2(X)	((X) << 1)
#define _sllmul4(X)	((X) << 2)
#define _sllmul2n(X,N)	((X) << (N))

#define _slldiv(X,Y)	sllmul((X), sllinv(Y))
#define _slldiv2(X)	((X) >> 1)
#define _slldiv4(X)	((X) >> 2)
#define _slldiv2n(X,N)	((X) >> (N))

/*
 * Constants (converted from double)
*/

#define CONST_0		0x0000000000000000LL	// 0.0
#define CONST_1		0x0000000100000000LL	// 1.0
#define CONST_neg1	0xffffffff00000000LL	// -1.0
#define CONST_2		0x0000000200000000LL 	// 2.0
#define CONST_3		0x0000000300000000LL	// 3.0
#define CONST_4		0x0000000400000000LL	// 4.0
#define CONST_10	0x0000000a00000000LL	// 10.0
#define CONST_10	0x0000000a00000000LL	// 10.0
#define CONST_1_2	0x0000000080000000LL	// 1.0 / 2.0
#define CONST_1_3	0x0000000055555555LL	// 1.0 / 3.0
#define CONST_1_4	0x0000000040000000LL	// 1.0 / 4.0
#define CONST_1_5	0x0000000033333333LL	// 1.0 / 5.0
#define CONST_1_6	0x000000002aaaaaaaLL	// 1.0 / 6.0
#define CONST_1_7	0x0000000024924924LL	// 1.0 / 7.0
#define CONST_1_8	0x0000000020000000LL	// 1.0 / 8.0
#define CONST_1_9	0x000000001c71c71cLL	// 1.0 / 9.0
#define CONST_1_10	0x0000000019999999LL	// 1.0 / 10.0
#define CONST_1_11	0x000000001745d174LL	// 1.0 / 11.0
#define CONST_1_12	0x0000000015555555LL	// 1.0 / 12.0
#define CONST_1_20	0x000000000cccccccLL	// 1.0 / 20.0
#define CONST_1_30	0x0000000008888888LL	// 1.0 / 30.0
#define CONST_1_42	0x0000000006186186LL	// 1.0 / 42.0
#define CONST_1_56	0x0000000004924924LL	// 1.0 / 56.0
#define CONST_1_72	0x00000000038e38e3LL	// 1.0 / 72.0
#define CONST_1_90	0x0000000002d82d82LL	// 1.0 / 90.0
#define CONST_1_110	0x000000000253c825LL	// 1.0 / 110.0
#define CONST_1_132	0x0000000001f07c1fLL	// 1.0 / 132.0
#define CONST_1_156	0x0000000001a41a41LL	// 1.0 / 156.0
#define CONST_P9999 0x00000000FFFFFFFFLL    // 0.999999999999

#define CONST_E		0x00000002b7e15162LL	// E
#define CONST_1_E	0x000000005e2d58d8LL	// 1 / E
#define CONST_SQRTE	0x00000001a61298e1LL	// sqrt(E)
#define CONST_1_SQRTE	0x000000009b4597e3LL	// 1 / sqrt(E)
#define CONST_LOG2_E	0x0000000171547652LL	// ln(E)
#define CONST_LOG10_E	0x000000006f2dec54LL	// log(E)
#define CONST_LN2	0x00000000b17217f7LL	// ln(2)
#define CONST_LN10	0x000000024d763776LL	// ln(10)

#define CONST_PI	0x00000003243f6a88LL	// PI
#define CONST_2PI	0x00000006487ED510LL	// PI
#define CONST_PI_2	0x00000001921fb544LL	// PI / 2
#define CONST_PI_4	0x00000000c90fdaa2LL	// PI / 4
#define CONST_1_PI	0x00000000517cc1b7LL	// 1 / PI
#define CONST_2_PI	0x00000000a2f9836eLL	// 2 / PI
#define CONST_180_PI  	0x000000394BB834C7LL	// 180 / PI 246083499207.51537232162612011973
#define CONST_PI_180	0x000000000477d1a8LL	// PI / 180 74961320.580677883103327681382757
#define CONST_2_SQRTPI	0x0000000120dd7504LL	// 2 / sqrt(PI)
#define CONST_SQRT2	0x000000016a09e667LL	// sqrt(2)
#define CONST_1_SQRT2	0x00000000b504f333LL	// 1 / sqrt(2)

#define CONST_FACT_0	0x0000000100000000LL	// 0!
#define CONST_FACT_1	0x0000000100000000LL	// 1!
#define CONST_FACT_2	0x0000000200000000LL	// 2!
#define CONST_FACT_3	0x0000000600000000LL	// 3!
#define CONST_FACT_4	0x0000001800000000LL	// 4!
#define CONST_FACT_5	0x0000007800000000LL	// 5!
#define CONST_FACT_6	0x000002d000000000LL	// 6!
#define CONST_FACT_7	0x000013b000000000LL	// 7!
#define CONST_FACT_8	0x00009d8000000000LL	// 8!
#define CONST_FACT_9	0x0005898000000000LL	// 9!
#define CONST_FACT_10	0x00375f0000000000LL	// 10!
#define CONST_FACT_11	0x0261150000000000LL	// 11!
#define CONST_FACT_12	0x1c8cfc0000000000LL	// 12!

#define CONST_MAX		0x7FFFFFFFFFFFFFFFLL  // 最大
#define CONST_MIN		0x8000000000000000LL	// 最小

/*
 * Convert integer to sll
 */

static __inline__ sll int2sll(int i)
{
	return _int2sll(i);
}

/*
 * Convert sll to integer (truncates)
 */

static __inline__ int sll2int(sll s)
{
	return _sll2int(s);
}

/*
 * Integer-part of sll (fractional-part set to 0)
 */

static __inline__ sll sllint(sll s)
{
	return _sllint(s);
}

/*
 * Fractional-part of sll (integer-part set to 0)
 */

static __inline__ sll sllfrac(sll s)
{
	return _sllfrac(s);
}

/*
 * Addition
 */

static __inline__ sll slladd(sll x, sll y)
{
	return _slladd(x, y);
}

/*
 * Negate
 */

static __inline__ sll sllneg(sll s)
{
	return _sllneg(s);
}

/*
 * Subtraction
 */

static __inline__ sll sllsub(sll x, sll y)
{
	return _sllsub(x, y);
}

/*
 * Multiply two sll values
 *
 * Description
 *
 *	Let a = A * 2^32 + a_h * 2^0 + a_l * 2^(-32)
 *	Let b = B * 2^32 + b_h * 2^0 + b_l * 2^(-32)
 *
 * 	Where:
 *
 *	*_h is the integer part
 *	*_l the fractional part
 *	A and B are the sign (0 for positive, -1 for negative).
 *
 *	a * b = (A * 2^32 + a_h * 2^0 + a_l * 2^-32)
 *		* (B * 2^32 + b_h * 2^0 + b_l * 2^-32)
 *
 *	Expanding the terms, we get:
 *
 *	= A * B * 2^64 + A * b_h * 2^32 + A * b_l * 2^0
 *	+ a_h * B * 2^32 + a_h * b_h * 2^0 + a_h * b_l * 2^-32
 *	+ a_l * B * 2^0 + a_l * b_h * 2^-32 + a_l * b_l * 2^-64
 *
 *	Grouping by powers of 2, we get:
 *
 *	= A * B * 2^64
 *	Meaningless overflow from sign extension - ignore
 *
 *	+ (A * b_h + a_h * B) * 2^32
 *	Overflow which we can't handle - ignore
 *
 *	+ (A * b_l + a_h * b_h + a_l * B) * 2^0
 *	We only need the low 32 bits of this term, as the rest is overflow
 *
 *	+ (a_h * b_l + a_l * b_h) * 2^-32
 *	We need all 64 bits of this term
 *
 *	+  a_l * b_l * 2^-64
 *	We only need the high 32 bits of this term, as the rest is underflow
 *
 *	Note that:
 *	a > 0 && b > 0: A =  0, B =  0 and the third term is a_h * b_h
 *	a < 0 && b > 0: A = -1, B =  0 and the third term is a_h * b_h - b_l
 *	a > 0 && b < 0: A =  0, B = -1 and the third term is a_h * b_h - a_l
 *	a < 0 && b < 0: A = -1, B = -1 and the third term is a_h * b_h - a_l - b_l
 */

/*
 * Multiplication by 2
 */

static __inline__ sll sllmul2(sll x)
{
	return _sllmul2(x);
}

/*
 * Multiplication by 4
 */

static __inline__ sll sllmul4(sll x)
{
	return _sllmul4(x);
}

/*
 * Multiplication by power of 2
 */

static __inline__ sll sllmul2n(sll x, int n)
{
	return _sllmul2n(x, n);
}

/*
 * Division
 */

static __inline__ sll slldiv(sll x, sll y)
{
	return _slldiv(x, y);
}

/*
 * Division by 2
 */

static __inline__ sll slldiv2(sll x)
{
	return _slldiv2(x);
}

/*
 * Division by 4
 */

static __inline__ sll slldiv4(sll x)
{
	return _slldiv4(x);
}

/*
 * Division by power of 2
 */

static __inline__ sll slldiv2n(sll x, int n)
{
	return _slldiv2n(x, n);
}

/*
 *
 * Calculate acos x, where |x| <= 1
 *
 * Description
 *
 *	acos x = pi / 2 - asin x
 *	acos x = pi / 2 - SUM[n=0,) C(2 * n, n) * x^(2 * n + 1) / (4^n * (2 * n + 1)), |x| <= 1
 *
 *	where C(n, r) = nCr = n! / (r! * (n - r)!)
 */

static __inline__ sll sllacos(sll x)
{
	return _sllsub(CONST_PI_2, sllasin(x));
}

/*
 * Trigonometric secant
 *
 * Description
 *
 *	sec x = 1 / cos x
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllsec(sll x)
{
	return sllinv(sllcos(x));
}

/*
 * Trigonometric cosecant
 *
 * Description
 *
 *	csc x = 1 / sin x
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllcsc(sll x)
{
	return sllinv(sllsin(x));
}

/*
 * Trigonometric cotangent
 *
 * Description
 *
 *	cot x = 1 / tan x
 *
 *	cot x = cos x / sin x
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllcot(sll x)
{
	return _slldiv(sllcos(x), sllsin(x));
}

/*
 * Hyperbolic cosine
 *
 * Description
 *
 *	cosh x = (e^x + e^(-x)) / 2
 *
 *	cosh x = 1 + x^2 / 2! + ... + x^(2 * N) / (2 * N)!
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllcosh(sll x)
{
	return _slldiv2(_slladd(sllexp(x), sllexp(_sllneg(x))));
}

/*
 * Hyperbolic sine
 *
 * Description
 *
 *	sinh x = (e^x - e^(-x)) / 2
 *
 *	sinh x = 1 + x^3 / 3! + ... + x^(2 * N + 1) / (2 * N + 1)!
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllsinh(sll x)
{
	return _slldiv2(_sllsub(sllexp(x), sllexp(_sllneg(x))));
}

/*
 * Hyperbolic tangent
 *
 * Description
 *
 *	tanh x = sinh x / cosh x
 *
 *	tanh x = (e^x - e^(-x)) / (e^x + e^(-x))
 *
 *	tanh x = (e^(2 * x) - 1) / (e^(2 * x) + 1)
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll slltanh(sll x)
{
	register sll e2x;

	e2x = sllexp(_sllmul2(x));

	return _slldiv(_sllsub(e2x, CONST_1), _slladd(e2x, CONST_1));
}

/*
 * Hyperbolic secant
 *
 * Description
 *
 *	sech x = 1 / cosh x
 *
 *	sech x = 2 / (e^x + e^(-x))
 *
 *	sech x = 2 * e^x / (e^(2 * x) + 1)
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllsech(sll x)
{
	return _slldiv(_sllmul2(sllexp(x)), _slladd(sllexp(_sllmul2(x)), CONST_1));
}

/*
 * Hyperbolic cosecant
 *
 * Description
 *
 *	csch x = = 1 / sinh x
 *
 *	csch x = 2 / (e^x - e^(-x))
 *
 *	csch x = 2 * e^x / (e^(2 * x) - 1)
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllcsch(sll x)
{
	return _slldiv(_sllmul2(sllexp(x)), _sllsub(sllexp(_sllmul2(x)), CONST_1));
}

/*
 * Hyperbolic cotangent
 *
 * Description
 *
 *	coth x =  1 / tanh x
 *
 *	coth x = cosh x / sinh x
 *
 *	coth x = (e^x + e^(-x)) / (e^x - e^(-x))
 *
 *	coth x = (e^(2 * x) + 1) / (e^(2 * x) - 1)
 *
 * An alternate algorithm, like a power series, would be more accurate.
 */

static __inline__ sll sllcoth(sll x)
{
	register sll e2x;

	e2x = sllexp(sllmul2(x));

	return _slldiv(_slladd(e2x, CONST_1), _sllsub(e2x, CONST_1));
}

/*
 * Floor
 *
 * Description
 *
 *	floor x = largest integer not larger than x
 */

static __inline__ sll sllfloor(sll x)
{
	register sll retval;

	retval = _sllint(x);

	return ((retval > x) ? _sllsub(retval, CONST_1): retval);
}

/*
 * Ceiling
 *
 * Description
 *
 *	ceil x = smallest integer not smaller than x
 */

static __inline__ sll sllceil(sll x)
{
	register sll retval;

	retval = _sllint(x);

	return ((retval < x) ? _slladd(retval, CONST_1): retval);
}

#define sllabs(x) ((x) < 0 ? -(x) : (x))
#define __VECTOR2_META__ "__VECTOR2_META__"
#define __VECTOR3_META__ "__VECTOR3_META__"
#define __ROT2_META__ "__ROT2_META__"
#define __ROT4_META__ "__ROT4_META__"
#define __METATABLE_NAME "__FIX_METATABLE__"

static int _mul[] = {1, 10, 100, 1000, 10000, 100000, 1000000};

typedef struct Vector2
{
	sll x;
	sll y;
}Vector2;

typedef struct Vector3
{
	sll x;
	sll y;
	sll z;
}Vector3;

typedef struct Vector4
{
	sll x;
	sll y;
	sll z;
	sll w;
	
}Vector4;


}

#endif