NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
math.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_NUMERIC_MATH_HPP__
2#define NEFORCE_CORE_NUMERIC_MATH_HPP__
3
11
14NEFORCE_BEGIN_NAMESPACE__
15
16NEFORCE_BEGIN_CONSTANTS__
17
37
38NEFORCE_INLINE17 constexpr decimal_t EULER = 2.71828182845904523536L;
39NEFORCE_INLINE17 constexpr decimal_t PI = 3.14159265358979323846L;
40NEFORCE_INLINE17 constexpr decimal_t PHI = 1.61803398874989484820L;
41NEFORCE_INLINE17 constexpr decimal_t SEMI_CIRCLE = 180.0L;
42NEFORCE_INLINE17 constexpr decimal_t CIRCLE = 360.0L;
43
45NEFORCE_INLINE17 constexpr decimal_t TWO_PI_HI = 6.28318530717958647692L;
47NEFORCE_INLINE17 constexpr decimal_t TWO_PI_LO = 2.44929359829470641435e-16L;
48
52NEFORCE_INLINE17 constexpr decimal_t DEFAULT_TOLERANCE = 1e-12L;
54NEFORCE_INLINE17 constexpr decimal_t LOOSE_TOLERANCE = 1e-9L;
55
61NEFORCE_INLINE17 constexpr uint64_t FIBONACCI_LIST[] = {
62 0, 1, 1, 2, 3, 5, 8, 13, 21,
63 34, 55, 89, 144, 233, 377, 610, 987, 1597,
64 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393,
65 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
66 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733,
67 1134903170, 1836311903, 2971215073, 4807526976, 7778742049};
68
69NEFORCE_INLINE17 constexpr uint32_t FIBONACCI_COUNT = extent_v<decltype(FIBONACCI_LIST)>;
70 // MathConstants
72
73NEFORCE_END_CONSTANTS__
74
147
148NEFORCE_CONST_FUNCTION constexpr int64_t safe_trunc(const decimal_t x) noexcept {
149 constexpr int64_t max_val = numeric_traits<int64_t>::max();
150 constexpr int64_t min_val = numeric_traits<int64_t>::min();
151 constexpr auto max_int64 = static_cast<decimal_t>(max_val);
152 constexpr auto min_int64 = static_cast<decimal_t>(min_val);
153
154 if (is_nan(x) || is_infinity(x)) {
155 return 0;
156 }
157
158 if (x >= max_int64) {
159 const auto result = static_cast<int64_t>(x);
160 return (result == max_val && x <= max_int64) ? result : 0;
161 }
162 if (x <= min_int64) {
163 const auto result = static_cast<int64_t>(x);
164 return (result == min_val && x >= min_int64) ? result : 0;
165 }
166 return static_cast<int64_t>(x);
167}
168
173NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 uint64_t safe_decimal_to_uint64(const decimal_t x) noexcept {
174 constexpr decimal_t TWO_POW_63 = 9223372036854775808.0L;
175 if (x >= TWO_POW_63) {
176 return static_cast<uint64_t>(x - TWO_POW_63) + 9223372036854775808ULL;
177 } else {
178 return static_cast<uint64_t>(x);
179 }
180}
181
190NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 uint64_t fibonacci(const uint32_t n) noexcept {
191 if (n < constants::FIBONACCI_COUNT) {
192 return constants::FIBONACCI_LIST[n];
193 }
194 uint64_t a = constants::FIBONACCI_LIST[constants::FIBONACCI_COUNT - 2];
195 uint64_t b = constants::FIBONACCI_LIST[constants::FIBONACCI_COUNT - 1];
196 for (uint32_t i = constants::FIBONACCI_COUNT; i <= n; ++i) {
197 const uint64_t c = a + b;
198 a = b;
199 b = c;
200 }
201 return b;
202}
203
211NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 uint64_t leonardo(const uint32_t n) noexcept {
212 return 2 * fibonacci(n + 1) - 1;
213}
214
221template <typename T>
222NEFORCE_PURE_FUNCTION constexpr T angular2radian(const T angular) noexcept {
223 static_assert(is_arithmetic_v<T>, "arithmetic required");
224 return angular * static_cast<T>(constants::PI) / static_cast<T>(constants::SEMI_CIRCLE);
225}
226
233template <typename T>
234NEFORCE_PURE_FUNCTION constexpr T radian2angular(const T radian) noexcept {
235 static_assert(is_arithmetic_v<T>, "arithmetic required");
236 return radian * (static_cast<T>(constants::SEMI_CIRCLE) / static_cast<T>(constants::PI));
237}
238
245template <typename T>
246NEFORCE_CONST_FUNCTION constexpr enable_if_t<is_signed_v<T>, T> absolute(const T x) noexcept {
247 return x > T(0) ? x : -x;
248}
249
256
257template <typename T>
258NEFORCE_CONST_FUNCTION constexpr enable_if_t<is_unsigned_v<T>, T> absolute(const T x) noexcept {
259 return x;
260}
261
270template <typename T>
271NEFORCE_CONST_FUNCTION constexpr const T& sum(const T& x) noexcept {
272 return x;
273}
274
283template <typename First, typename... Rests, enable_if_t<(sizeof...(Rests) > 0), int> = 0>
284constexpr decltype(auto) sum(First first, Rests... args) {
285 return first + _NEFORCE sum(args...);
286}
287
294template <typename... Args, enable_if_t<(sizeof...(Args) > 0), int> = 0>
295constexpr decltype(auto) average(Args... args) {
296 return _NEFORCE sum(args...) / sizeof...(Args);
297}
298
305template <typename T>
306NEFORCE_CONSTEXPR14 int sign(const T& value) noexcept {
307 static_assert(is_arithmetic_v<T>, "arithmetic required");
308 constexpr T zero = T(0);
309 if (value > zero) {
310 return 1;
311 }
312 if (value < zero) {
313 return -1;
314 }
315 return 0;
316}
317
325template <typename T>
326NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 T gcd(const T& m, const T& n) noexcept {
327 T x = _NEFORCE absolute(m), y = _NEFORCE absolute(n);
328 constexpr T zero = T(0);
329 while (y != zero) {
330 T t = x % y;
331 x = y;
332 y = t;
333 }
334 return x;
335}
336
344template <typename T>
345NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 T lcm(const T& m, const T& n) noexcept {
346 return (m / _NEFORCE gcd(m, n)) * n;
347}
348
357template <typename T>
358NEFORCE_CONSTEXPR14 enable_if_t<is_floating_point_v<T>, T> mod(const T x, const T y) {
359 if (_NEFORCE is_nan(x) || _NEFORCE is_nan(y)) {
361 }
362 if (y == 0) {
363 NEFORCE_THROW_EXCEPTION(math_exception("zero can not be dividend."));
364 }
365 if (_NEFORCE is_infinity(x) || _NEFORCE is_infinity(y)) {
367 }
368 return x - static_cast<make_integer_t<sizeof(T)>>(x / y) * y;
369}
370
379template <typename T>
380NEFORCE_CONSTEXPR14 enable_if_t<is_integral_v<T>, T> mod(const T x, const T y) {
381 if (y == 0) {
382 NEFORCE_THROW_EXCEPTION(math_exception("zero can not be dividend."));
383 }
384 return x % y;
385}
386
396template <typename T>
397NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 T power(const T& x, uint32_t n) noexcept {
398 static_assert(is_arithmetic_v<T>, "arithmetic required");
399 if (n == 0) {
400 return 1;
401 }
402 T result(1);
403 T base = x;
404 while (n > 0) {
405 if (n % 2 == 1) {
406 result *= base;
407 }
408 base *= base;
409 n /= 2;
410 }
411 return result;
412}
413
419NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t exponential(const uint32_t n) noexcept {
420 return power(constants::EULER, n);
421}
422
430NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t logarithm_e(const decimal_t x) noexcept {
431 if (is_nan(x)) {
432 return x;
433 }
434 if (x < 0.0L) {
436 }
437 if (x == 0.0L) {
438 return static_cast<decimal_t>(-numeric_traits<decimal_t>::infinity());
439 }
440 if (is_infinity(x) && x > 0) {
441 return x;
442 }
443
444 int64_t k = 0;
445 decimal_t m = x;
446
447 if (m >= 2.0L) {
448 while (m >= 2.0L) {
449 m *= 0.5L;
450 ++k;
451 }
452 } else if (m < 1.0L) {
453 while (m < 1.0L) {
454 m *= 2.0L;
455 --k;
456 }
457 }
458
459 const decimal_t a = (m - 1.0L) / (m + 1.0L);
460 const decimal_t a2 = a * a;
461 decimal_t term = a;
462 decimal_t s = a;
463 decimal_t n = 1.0L;
464
465 while (absolute(term) > constants::MACHINE_EPSILON * absolute(s)) {
466 term *= a2;
467 n += 2.0L;
468 s += term / n;
469 }
470
471 constexpr decimal_t LN2 = 0.69314718055994530941723212145817656807L;
472 return 2.0L * s + static_cast<decimal_t>(k) * LN2;
473}
474
481NEFORCE_CONSTEXPR14 decimal_t logarithm(const decimal_t x, const uint32_t base) {
482 const decimal_t under = logarithm_e(base);
483 if (under == 0.0L) {
484 NEFORCE_THROW_EXCEPTION(math_exception("zero can not be dividend."));
485 }
486 return logarithm_e(x) / under;
487}
488
494NEFORCE_CONSTEXPR14 decimal_t logarithm_2(const decimal_t x) { return logarithm(x, 2); }
495
501NEFORCE_CONSTEXPR14 decimal_t logarithm_10(const decimal_t x) { return logarithm(x, 10); }
502
511NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t
512square_root(const decimal_t x, const decimal_t precise = constants::DEFAULT_TOLERANCE) noexcept {
513 if (is_nan(x)) {
514 return x;
515 }
516 if (x < 0.0L) {
518 }
519 if (x == 0.0L) {
520 return x;
521 }
522 if (is_infinity(x) && x > 0) {
523 return x;
524 }
525
526 decimal_t guess = x * 0.5L;
527 decimal_t prev = 0.0L;
528 do {
529 prev = guess;
530 guess = 0.5L * (prev + x / prev);
531 } while (absolute(guess - prev) > precise * absolute(guess));
532 return guess;
533}
534
543NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t
544cube_root(const decimal_t x, const decimal_t precise = constants::DEFAULT_TOLERANCE) noexcept {
545 if (is_nan(x)) {
546 return x;
547 }
548 if (is_infinity(x)) {
549 return x;
550 }
551 if (x == 0.0L) {
552 return x;
553 }
554
555 const bool negative = x < 0.0L;
556 const decimal_t v = negative ? -x : x;
557
558 decimal_t guess = v > 1.0L ? v / 3.0L : v;
559 decimal_t prev = 0.0L;
560 do {
561 prev = guess;
562 guess = (2.0L * prev + v / (prev * prev)) / 3.0L;
563 } while (absolute(guess - prev) > precise * absolute(guess));
564
565 return negative ? -guess : guess;
566}
567
573NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 uint64_t factorial(const uint32_t n) noexcept {
574 uint64_t result = 1;
575 for (uint32_t i = 2; i <= n; ++i) {
576 result *= i;
577 }
578 return result;
579}
580
586NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t floor(const decimal_t x) noexcept {
587 if (!is_finite(x)) {
588 return x;
589 }
590
591 constexpr auto TWO_POW_64 = static_cast<decimal_t>(numeric_traits<uint64_t>::max());
592 if (x >= 0.0L) {
593 if (x >= TWO_POW_64) {
594 return x;
595 }
596 return static_cast<decimal_t>(safe_decimal_to_uint64(x));
597 } else {
598 const decimal_t pos = -x;
599 if (pos >= TWO_POW_64) {
600 return x;
601 }
602 const auto floor_pos = static_cast<decimal_t>(safe_decimal_to_uint64(pos));
603 if (absolute(pos - floor_pos) < constants::MACHINE_EPSILON) {
604 return -floor_pos;
605 } else {
606 return -(floor_pos + 1.0L);
607 }
608 }
609}
610
617NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t floor(const decimal_t x, const uint32_t bit) noexcept {
618 const decimal_t factor = power(10.0L, bit);
619 return floor(x * factor) / factor;
620}
621
622NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 bool is_even_integer(const decimal_t x) noexcept {
623 const decimal_t half = x * 0.5L;
624 return absolute(half - floor(half)) < constants::MACHINE_EPSILON;
625}
626
632NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t ceil(const decimal_t x) noexcept {
633 if (!is_finite(x)) {
634 return x;
635 }
636
637 constexpr auto TWO_POW_64 = static_cast<decimal_t>(numeric_traits<uint64_t>::max());
638 if (x >= 0.0L) {
639 if (x >= TWO_POW_64) {
640 return x;
641 }
642 const auto floor_x = static_cast<decimal_t>(safe_decimal_to_uint64(x));
643 if (absolute(x - floor_x) < constants::MACHINE_EPSILON) {
644 return floor_x;
645 } else {
646 return floor_x + 1.0L;
647 }
648 } else {
649 const decimal_t pos = -x;
650 if (pos >= TWO_POW_64) {
651 return x;
652 }
653 const uint64_t floor_pos = safe_decimal_to_uint64(pos);
654 return -static_cast<decimal_t>(floor_pos);
655 }
656}
657
664NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t ceil(const decimal_t x, const uint32_t bit) noexcept {
665 const decimal_t factor = power(10.0L, bit);
666 return ceil(x * factor) / factor;
667}
668
674NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t round(const decimal_t x) noexcept {
675 if (!is_finite(x)) {
676 return x;
677 }
678
679 const decimal_t abs_x = absolute(x);
680 const decimal_t int_part = floor(abs_x);
681 const decimal_t frac = abs_x - int_part;
682
683 if (frac < 0.5L) {
684 return (x < 0.0L) ? -int_part : int_part;
685 }
686 if (frac > 0.5L) {
687 return (x < 0.0L) ? -(int_part + 1.0L) : (int_part + 1.0L);
688 }
689
690 if (is_even_integer(int_part)) {
691 return (x < 0.0L) ? -int_part : int_part;
692 } else {
693 return (x < 0.0L) ? -(int_part + 1.0L) : (int_part + 1.0L);
694 }
695}
696
697
704NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t floor_bit(const decimal_t x, const uint32_t bit) noexcept {
705 const decimal_t factor = power(10.0L, bit);
706 return floor(x * factor) / factor;
707}
708
715NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t ceil_bit(const decimal_t x, const uint32_t bit) noexcept {
716 const decimal_t factor = power(10.0L, bit);
717 return ceil(x * factor) / factor;
718}
719
726NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t round_bit(const decimal_t x, const uint32_t bit) noexcept {
727 return x < 0 ? ceil_bit(x - 0.5 / power(10.0, bit), bit) : floor_bit(x + 0.5 / power(10.0, bit), bit);
728}
729
736NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t truncate_bit(const decimal_t x, const uint32_t bit) noexcept {
737 return x < 0 ? ceil_bit(x, bit) : floor_bit(x, bit);
738}
739
740
747NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t round(const decimal_t x, const uint32_t bit) noexcept {
748 const decimal_t factor = power(10.0L, bit);
749 return round(x * factor) / factor;
750}
751
758NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t truncate(const decimal_t x, const int bit) noexcept {
759 const decimal_t factor = power(10.0L, static_cast<uint32_t>(absolute(bit)));
760 return (x < 0 ? ceil(x * factor, 0) : floor(x * factor, 0)) / factor;
761}
762
768NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t truncate(const decimal_t x) noexcept {
769 if (!is_finite(x)) {
770 return x;
771 }
772 return static_cast<decimal_t>(safe_trunc(x));
773}
774
783NEFORCE_CONSTEXPR14 bool around_multiple(const decimal_t x, const decimal_t axis,
784 const decimal_t toler = constants::DEFAULT_TOLERANCE) {
785 if (absolute(axis) < constants::MACHINE_EPSILON) {
786 NEFORCE_THROW_EXCEPTION(math_exception("Axis Cannot be 0"));
787 }
788 const decimal_t multi = round(x / axis) * axis;
789 return absolute(x - multi) < toler;
790}
791
798NEFORCE_CONSTEXPR14 bool around_pi(const decimal_t x, const decimal_t toler = constants::LOOSE_TOLERANCE) {
799 return around_multiple(x, constants::PI, toler);
800}
801
808NEFORCE_CONSTEXPR14 bool around_zero(const decimal_t x, const decimal_t toler = constants::LOOSE_TOLERANCE) noexcept {
809 return absolute(x) < toler;
810}
811
812
821NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t remainder(const decimal_t x, const decimal_t y) noexcept {
822 if (is_nan(x) || is_nan(y) || is_infinity(x) || y == 0.0L) {
824 }
825 return x - y * round(x / y);
826}
827
833NEFORCE_CONST_FUNCTION constexpr decimal_t float_part(const decimal_t x) noexcept {
834 return x - static_cast<decimal_t>(safe_trunc(x));
835}
836
845NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t float_apart(decimal_t x, int64_t* int_ptr) noexcept {
846 *int_ptr = safe_trunc(x);
847 return x - static_cast<decimal_t>(*int_ptr);
848}
849
851NEFORCE_BEGIN_INNER__
852
853NEFORCE_CONSTEXPR14 void reduce_arg_sincos(decimal_t& x, int& quadrant) noexcept {
854 if (x < 0.0L) {
855 x = -x;
856 quadrant = 3;
857 } else {
858 quadrant = 0;
859 }
860
861 constexpr decimal_t HALF_PI_HI = 1.57079632679489661923L;
862 constexpr decimal_t HALF_PI_LO = 6.12323399573676603587e-17L;
863 constexpr decimal_t INV_HALF_PI = 0.63661977236758134308L;
864
865 const decimal_t kd = round(x * INV_HALF_PI);
866 const auto k = static_cast<int64_t>(kd);
867 quadrant = static_cast<int>(quadrant + (k & 3)) & 3;
868
869 decimal_t t = kd * HALF_PI_HI;
870 x = x - t;
871 t = kd * HALF_PI_LO;
872 x = x - t;
873}
874
875NEFORCE_CONSTEXPR14 void sincos_taylor(const decimal_t x, decimal_t& sin_val, decimal_t& cos_val) noexcept {
876 const decimal_t x2 = x * x;
877
878 decimal_t term_sin = x;
879 decimal_t sum_sin = x;
880
881 decimal_t term_cos = 1.0L;
882 decimal_t sum_cos = 1.0L;
883
884 decimal_t i = 1.0L;
885 bool sin_done = false, cos_done = false;
886
887 while (!sin_done || !cos_done) {
888 if (!sin_done) {
889 term_sin = -term_sin * x2 / ((i + 1.0L) * (i + 2.0L));
890 sum_sin += term_sin;
891 if (absolute(term_sin) <= constants::MACHINE_EPSILON * absolute(sum_sin)) {
892 sin_done = true;
893 }
894 }
895 if (!cos_done) {
896 term_cos = -term_cos * x2 / (i * (i + 1.0L));
897 sum_cos += term_cos;
898 if (absolute(term_cos) <= constants::MACHINE_EPSILON * absolute(sum_cos)) {
899 cos_done = true;
900 }
901 }
902 i += 2.0L;
903 }
904
905 sin_val = sum_sin;
906 cos_val = sum_cos;
907}
908
909NEFORCE_END_INNER__
911
919NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t sine(decimal_t x) noexcept {
920 if (is_nan(x) || is_infinity(x)) {
922 }
923
924 int quadrant = 0;
925 inner::reduce_arg_sincos(x, quadrant);
926
927 decimal_t sin_x = 0.0L, cos_x = 0.0L;
928 inner::sincos_taylor(x, sin_x, cos_x);
929
930 switch (quadrant) {
931 case 0:
932 return sin_x;
933 case 1:
934 return cos_x;
935 case 2:
936 return -sin_x;
937 default:
938 return -cos_x;
939 }
940}
941
949NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t cosine(decimal_t x) noexcept {
950 if (is_nan(x) || is_infinity(x)) {
952 }
953
954 int quadrant = 0;
955 inner::reduce_arg_sincos(x, quadrant);
956 decimal_t sin_x = 0.0L, cos_x = 0.0L;
957 inner::sincos_taylor(x, sin_x, cos_x);
958
959 switch (quadrant) {
960 case 0:
961 return cos_x;
962 case 1:
963 return -sin_x;
964 case 2:
965 return -cos_x;
966 default:
967 return sin_x;
968 }
969}
970
977NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t tangent(decimal_t x) noexcept {
978 if (is_nan(x) || is_infinity(x)) {
980 }
981
982 int quadrant = 0;
983 inner::reduce_arg_sincos(x, quadrant);
984 decimal_t sin_x = 0.0L, cos_x = 0.0L;
985 inner::sincos_taylor(x, sin_x, cos_x);
986
987 decimal_t s = 0.0L, c = 0.0L;
988 switch (quadrant) {
989 case 0:
990 s = sin_x;
991 c = cos_x;
992 break;
993 case 1:
994 s = cos_x;
995 c = -sin_x;
996 break;
997 case 2:
998 s = -sin_x;
999 c = -cos_x;
1000 break;
1001 default:
1002 s = -cos_x;
1003 c = sin_x;
1004 break;
1005 }
1006
1007 if (around_zero(c, constants::LOOSE_TOLERANCE)) {
1008 constexpr auto inf = static_cast<decimal_t>(numeric_traits<decimal_t>::infinity());
1009 return (s > 0) ? inf : -inf;
1010 }
1011 return s / c;
1012}
1013
1020NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t cotangent(const decimal_t x) { return 1.0L / tangent(x); }
1021
1029NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t arctangent(decimal_t x) noexcept {
1030 if (is_nan(x)) {
1031 return x;
1032 }
1033 if (is_infinity(x)) {
1034 return (x > 0) ? constants::PI / 2 : -constants::PI / 2;
1035 }
1036
1037 bool negative = x < 0.0L;
1038 if (negative) {
1039 x = -x;
1040 }
1041
1042 bool recip = false;
1043 if (x > 1.0L) {
1044 x = 1.0L / x;
1045 recip = true;
1046 }
1047
1048 x = x / (1.0L + square_root(1.0L + x * x));
1049 x = x / (1.0L + square_root(1.0L + x * x));
1050
1051 const decimal_t x2 = x * x;
1052 decimal_t term = x, s = x, n = 1.0L;
1053 while (absolute(term) > constants::MACHINE_EPSILON * absolute(s)) {
1054 term *= -x2;
1055 n += 2.0L;
1056 s += term / n;
1057 }
1058
1059 decimal_t result = 4.0L * s;
1060 if (recip) {
1061 result = constants::PI / 2 - result;
1062 }
1063 if (negative) {
1064 result = -result;
1065 }
1066 return result;
1067}
1068
1074NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t arcsine(const decimal_t x) noexcept {
1075 if (is_nan(x)) {
1076 return x;
1077 }
1078 if (absolute(x) > 1.0L) {
1080 }
1081 if (x == 1.0L) {
1082 return constants::PI / 2;
1083 }
1084 if (x == -1.0L) {
1085 return -constants::PI / 2;
1086 }
1087 return arctangent(x / square_root(1.0L - x * x));
1088}
1089
1095NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 decimal_t arccosine(const decimal_t x) noexcept {
1096 if (is_nan(x)) {
1097 return x;
1098 }
1099 if (absolute(x) > 1.0L) {
1101 }
1102 if (x == 1.0L) {
1103 return 0.0L;
1104 }
1105 if (x == -1.0L) {
1106 return constants::PI;
1107 }
1108 return constants::PI / 2 - arcsine(x);
1109}
1110 // MathFunctions
1112
1113NEFORCE_END_NAMESPACE__
1114#endif // NEFORCE_CORE_NUMERIC_MATH_HPP__
static constexpr T infinity() noexcept
获取正无穷大表示
static constexpr T max() noexcept
获取类型的最大值
static constexpr T quiet_nan() noexcept
获取安静nan表示
static constexpr T epsilon() noexcept
获取机器精度
static constexpr T min() noexcept
获取类型的最小值
异常处理框架
constexpr size_t extent_v
extent的便捷变量模板
constexpr bool is_arithmetic_v
is_arithmetic的便捷变量模板
unsigned int uint32_t
32位无符号整数类型
long double decimal_t
扩展精度浮点数类型
long long int64_t
64位有符号整数类型
unsigned long long uint64_t
64位无符号整数类型
constexpr Iterator prev(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的前一个位置
constexpr decimal_t EULER
自然常数 e
constexpr decimal_t LOOSE_TOLERANCE
宽松容差
constexpr uint32_t FIBONACCI_COUNT
斐波那契数列预计算数量
constexpr decimal_t CIRCLE
全圆角度 360° (角度制)
constexpr decimal_t SEMI_CIRCLE
半圆角度 180° (角度制)
constexpr decimal_t PHI
黄金分割比 φ
constexpr decimal_t MACHINE_EPSILON
机器精度
constexpr uint64_t FIBONACCI_LIST[]
预计算的斐波那契数列
constexpr decimal_t TWO_PI_HI
高精度 2π 高位
constexpr decimal_t DEFAULT_TOLERANCE
默认容差
constexpr decimal_t PI
圆周率 π (弧度制)
constexpr decimal_t TWO_PI_LO
高精度 2π 低位
constexpr decimal_t truncate_bit(const decimal_t x, const uint32_t bit) noexcept
截断到指定位数
constexpr decimal_t float_apart(decimal_t x, int64_t *int_ptr) noexcept
分离整数和小数部分
constexpr decimal_t exponential(const uint32_t n) noexcept
计算e的n次幂
constexpr bool around_pi(const decimal_t x, const decimal_t toler=constants::LOOSE_TOLERANCE)
判断是否接近π的整数倍
constexpr enable_if_t< is_floating_point_v< T >, T > mod(const T x, const T y)
浮点数取模运算
constexpr decimal_t arccosine(const decimal_t x) noexcept
计算反余弦值
constexpr int sign(const T &value) noexcept
获取数值的符号
constexpr decimal_t floor(const decimal_t x) noexcept
向下取整
constexpr decimal_t sine(decimal_t x) noexcept
计算正弦值
constexpr decimal_t cube_root(const decimal_t x, const decimal_t precise=constants::DEFAULT_TOLERANCE) noexcept
计算立方根
constexpr decimal_t floor_bit(const decimal_t x, const uint32_t bit) noexcept
向下舍入到指定位数
constexpr decimal_t tangent(decimal_t x) noexcept
计算正切值
constexpr uint64_t factorial(const uint32_t n) noexcept
计算阶乘
constexpr decimal_t square_root(const decimal_t x, const decimal_t precise=constants::DEFAULT_TOLERANCE) noexcept
计算平方根
constexpr decimal_t ceil(const decimal_t x) noexcept
向上取整
constexpr decimal_t logarithm_e(const decimal_t x) noexcept
计算自然对数
constexpr decimal_t arctangent(decimal_t x) noexcept
计算反正切值
constexpr decimal_t cotangent(const decimal_t x)
计算余切值
constexpr decimal_t cosine(decimal_t x) noexcept
计算余弦值
constexpr decimal_t truncate(const decimal_t x, const int bit) noexcept
截断
constexpr uint64_t leonardo(const uint32_t n) noexcept
计算莱昂纳多数
constexpr T angular2radian(const T angular) noexcept
角度转弧度
constexpr T gcd(const T &m, const T &n) noexcept
计算最大公约数
constexpr decimal_t logarithm_2(const decimal_t x)
计算以2为底的对数
constexpr decltype(auto) average(Args... args)
计算平均值
constexpr T radian2angular(const T radian) noexcept
弧度转角度
constexpr decimal_t float_part(const decimal_t x) noexcept
获取小数部分
constexpr enable_if_t< is_signed_v< T >, T > absolute(const T x) noexcept
取绝对值(有符号数版本)
constexpr bool around_zero(const decimal_t x, const decimal_t toler=constants::LOOSE_TOLERANCE) noexcept
判断是否接近零
constexpr decimal_t logarithm(const decimal_t x, const uint32_t base)
计算任意底数的对数
constexpr decimal_t ceil_bit(const decimal_t x, const uint32_t bit) noexcept
向上舍入到指定位数
constexpr uint64_t fibonacci(const uint32_t n) noexcept
计算斐波那契数
constexpr decimal_t arcsine(const decimal_t x) noexcept
计算反正弦值
constexpr bool around_multiple(const decimal_t x, const decimal_t axis, const decimal_t toler=constants::DEFAULT_TOLERANCE)
判断是否接近某个倍数值
constexpr const T & sum(const T &x) noexcept
单参数求和
constexpr uint64_t safe_decimal_to_uint64(const decimal_t x) noexcept
将非负 decimal_t 安全转换为 uint64_t(避免 >= 2^63 时的 UB)
constexpr T power(const T &x, uint32_t n) noexcept
幂运算
constexpr decimal_t logarithm_10(const decimal_t x)
计算以10为底的对数
constexpr decimal_t round(const decimal_t x) noexcept
四舍五入
constexpr T lcm(const T &m, const T &n) noexcept
计算最小公倍数
constexpr decimal_t remainder(const decimal_t x, const decimal_t y) noexcept
计算余数
constexpr decimal_t round_bit(const decimal_t x, const uint32_t bit) noexcept
四舍五入到指定位数
constexpr bool is_infinity(const T x) noexcept
检查浮点数是否为无穷大
constexpr bool is_nan(const T x) noexcept
检查浮点数是否为NaN
constexpr bool is_finite(const T x) noexcept
检查浮点数是否为有限值
typename make_integer< Size, IsSigned >::type make_integer_t
make_integer的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
数值类型特性检查
数学计算异常