├── .gitignore
├── LispLib
├── LispLib.vcxproj
├── LispLib.vcxproj.filters
├── LuaLib.sln
├── lisp.c
└── lisp.h
├── NtLisp.sln
├── NtLisp
├── NtLisp.vcxproj
├── NtLisp.vcxproj.filters
├── crt
│ ├── crt.h
│ ├── io.c
│ ├── libmd.h
│ ├── libmd
│ │ ├── __cos.c
│ │ ├── __expo2.c
│ │ ├── __rem_pio2.c
│ │ ├── __rem_pio2_large.c
│ │ ├── __sin.c
│ │ ├── __tan.c
│ │ ├── _fltused.c
│ │ ├── acos.c
│ │ ├── acosh.c
│ │ ├── asin.c
│ │ ├── asinh.c
│ │ ├── atan.c
│ │ ├── atan2.c
│ │ ├── atanh.c
│ │ ├── ceil.c
│ │ ├── copysign.c
│ │ ├── cos.c
│ │ ├── cosh.c
│ │ ├── erf.c
│ │ ├── exp.c
│ │ ├── expm1.c
│ │ ├── fabs.c
│ │ ├── floor.c
│ │ ├── fmod.c
│ │ ├── fpclassify.c
│ │ ├── frexp.c
│ │ ├── ldexp.c
│ │ ├── lgamma.c
│ │ ├── log.c
│ │ ├── log10.c
│ │ ├── log1p.c
│ │ ├── modf.c
│ │ ├── nearbyint.c
│ │ ├── pow.c
│ │ ├── rint.c
│ │ ├── scalbn.c
│ │ ├── signbit.c
│ │ ├── sin.c
│ │ ├── sinh.c
│ │ ├── sqrt.c
│ │ ├── tan.c
│ │ ├── tanh.c
│ │ ├── tgamma.c
│ │ └── trunc.c
│ ├── memory.cpp
│ ├── misc.c
│ ├── stdint.h
│ └── string.c
├── driver_io.hpp
├── logger.hpp
└── main.cpp
├── NtLispRepl
├── NtLispRepl.vcxproj
├── NtLispRepl.vcxproj.filters
└── main.cpp
├── README.md
└── vmware_03-17-34.png
/.gitignore:
--------------------------------------------------------------------------------
1 | *.db
2 | *.ipch
3 | *.opendb
4 | *.user
5 | *.log
6 | *.exe
7 | *.tlog
8 | *.obj
9 | *.exp
10 | *.pdb
11 | *.lib
12 | *.suo
13 | *.ilk
14 | *.db-shm
15 | *.db-wal
16 | .vs/
17 | Debug/
18 | Release/
19 | x64/
20 |
--------------------------------------------------------------------------------
/LispLib/LispLib.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | 16.0
29 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}
30 | Win32Proj
31 | LuaLib
32 | 10.0.19041.0
33 |
34 |
35 |
36 | StaticLibrary
37 | true
38 | WindowsKernelModeDriver10.0
39 | Unicode
40 |
41 |
42 | StaticLibrary
43 | false
44 | WindowsKernelModeDriver10.0
45 | true
46 | Unicode
47 |
48 |
49 | StaticLibrary
50 | true
51 | WindowsKernelModeDriver10.0
52 | Unicode
53 |
54 |
55 | StaticLibrary
56 | false
57 | WindowsKernelModeDriver10.0
58 | true
59 | Unicode
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | true
81 | $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH);
82 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath)
83 |
84 |
85 | true
86 | $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
87 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath);
88 |
89 |
90 | false
91 | $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH);
92 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath)
93 |
94 |
95 | false
96 | $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
97 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath);
98 |
99 |
100 |
101 | NotUsing
102 | Level3
103 | true
104 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
105 | true
106 | pch.h
107 | false
108 |
109 |
110 | Windows
111 | true
112 |
113 |
114 | true
115 |
116 |
117 |
118 |
119 | NotUsing
120 | Level3
121 | true
122 | _NO_CRT_STDIO_INLINE;_CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;%(PreprocessorDefinitions)
123 | true
124 | pch.h
125 | false
126 |
127 |
128 | Windows
129 | true
130 |
131 |
132 |
133 |
134 | true
135 |
136 |
137 |
138 |
139 | NotUsing
140 | Level3
141 | true
142 | true
143 | true
144 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
145 | true
146 | pch.h
147 | false
148 |
149 |
150 | Windows
151 | true
152 | true
153 | true
154 |
155 |
156 | true
157 |
158 |
159 |
160 |
161 | NotUsing
162 | Level3
163 | true
164 | true
165 | true
166 | _NO_CRT_STDIO_INLINE;_CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions)
167 | true
168 | pch.h
169 | false
170 |
171 |
172 | Windows
173 | true
174 | true
175 | true
176 |
177 |
178 |
179 |
180 | true
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/LispLib/LispLib.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LispLib/LuaLib.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29709.97
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LuaLib", "LuaLib.vcxproj", "{71FC9FC1-F46F-41D4-913E-07298D6E8220}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x64.ActiveCfg = Debug|x64
17 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x64.Build.0 = Debug|x64
18 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x86.ActiveCfg = Debug|Win32
19 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x86.Build.0 = Debug|Win32
20 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x64.ActiveCfg = Release|x64
21 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x64.Build.0 = Release|x64
22 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x86.ActiveCfg = Release|Win32
23 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {0E812DA3-D166-4D3C-9218-E8BB24A7A288}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/LispLib/lisp.h:
--------------------------------------------------------------------------------
1 | #ifndef LISP_H
2 | #define LISP_H
3 |
4 | /* https://github.com/justinmeiners/lisp-interpreter
5 | Created By: Justin Meiners (https://justinmeiners.github.io)
6 | License: MIT
7 |
8 | Build without standard library. (subset of MIT Scheme)
9 | The basic manipulation functions are still available in C.
10 | #define LISP_NO_LIB 1
11 |
12 | Build without functions which give lisp access to the system,
13 | such as file access.
14 | #define LISP_NO_SYSTEM_LIB 1
15 |
16 | Additional options: override how much data
17 | the parser reads into memory at once from a file.
18 | #define LISP_FILE_CHUNK_SIZE 4096
19 |
20 | */
21 |
22 | #include
23 |
24 | #define LISP_DEBUG 0
25 | #define LISP_NO_SYSTEM_LIB 1
26 |
27 | /* how much data the parser reads
28 | into memory at once from a file */
29 | #define LISP_FILE_CHUNK_SIZE 4096
30 |
31 |
32 | typedef enum
33 | {
34 | LISP_NULL = 0,
35 | LISP_REAL, // decimal/floating point type
36 | LISP_INT, // integer type
37 | LISP_CHAR,
38 | LISP_PAIR, // cons pair (car, cdr)
39 | LISP_SYMBOL, // unquoted strings
40 | LISP_STRING, // quoted strings
41 | LISP_LAMBDA, // user defined lambda
42 | LISP_FUNC, // C function
43 | LISP_TABLE, // key/value storage
44 | LISP_VECTOR, // heterogenous array but contiguous allocation
45 | } LispType;
46 |
47 | typedef enum
48 | {
49 | LISP_ERROR_NONE = 0,
50 | LISP_ERROR_FILE_OPEN,
51 | LISP_ERROR_PAREN_UNEXPECTED,
52 | LISP_ERROR_PAREN_EXPECTED,
53 | LISP_ERROR_DOT_UNEXPECTED,
54 | LISP_ERROR_BAD_TOKEN,
55 |
56 | LISP_ERROR_BAD_QUOTE,
57 | LISP_ERROR_BAD_DEFINE,
58 | LISP_ERROR_BAD_SET,
59 | LISP_ERROR_BAD_COND,
60 | LISP_ERROR_BAD_AND,
61 | LISP_ERROR_BAD_OR,
62 | LISP_ERROR_BAD_LET,
63 | LISP_ERROR_BAD_LAMBDA,
64 |
65 | LISP_ERROR_UNKNOWN_VAR,
66 | LISP_ERROR_BAD_OP,
67 | LISP_ERROR_UNKNOWN_EVAL,
68 | LISP_ERROR_OUT_OF_BOUNDS,
69 |
70 | LISP_ERROR_BAD_ARG,
71 | } LispError;
72 |
73 | typedef struct
74 | {
75 | union LispVal
76 | {
77 | float real_val;
78 | int int_val;
79 | void* ptr_val;
80 | } val;
81 |
82 | LispType type;
83 | } Lisp;
84 |
85 | typedef struct
86 | {
87 | struct LispImpl* impl;
88 | } LispContext;
89 |
90 | typedef Lisp(*LispCFunc)(Lisp, LispError*, LispContext);
91 |
92 | /* no need to change these, just use the _opt variant */
93 | #define LISP_DEFAULT_SYMBOL_TABLE_SIZE 512
94 | #define LISP_DEFAULT_PAGE_SIZE 32768
95 | #define LISP_DEFAULT_STACK_DEPTH 1024
96 |
97 | // SETUP
98 | // -----------------------------------------
99 | #ifndef LISP_NO_LIB
100 | LispContext lisp_init_lib(void);
101 | LispContext lisp_init_lib_opt(int symbol_table_size, size_t stack_depth, size_t page_size);
102 | #endif
103 |
104 | LispContext lisp_init_empty(void);
105 | LispContext lisp_init_empty_opt(int symbol_table_size, size_t stack_depth, size_t page_size);
106 | void lisp_shutdown(LispContext ctx);
107 |
108 | // garbage collection.
109 | // this will free all objects which are not reachable from root_to_save or the global env
110 | Lisp lisp_collect(Lisp root_to_save, LispContext ctx);
111 |
112 | // REPL
113 | // -----------------------------------------
114 |
115 | // reads text raw s-expressions. But does not apply any syntax expansions (equivalent to quoting the whole structure).
116 | // This is primarily for using Lisp as JSON/XML
117 | // For code call expand after reading
118 | Lisp lisp_read(const char* text, LispError* out_error, LispContext ctx);
119 | Lisp lisp_read_file(FILE* file, LispError* out_error, LispContext ctx);
120 | Lisp lisp_read_path(const char* path, LispError* out_error, LispContext ctx);
121 |
122 | // expands special Lisp forms (For code)
123 | // The default eval will do this for you, but this can prepare statements
124 | // that are run multiple times
125 | Lisp lisp_expand(Lisp lisp, LispError* out_error, LispContext ctx);
126 |
127 | // evaluate a lisp expression
128 | Lisp lisp_eval_opt(Lisp expr, Lisp env, LispError* out_error, LispContext ctx);
129 | // same as above but uses global environment
130 | Lisp lisp_eval(Lisp expr, LispError* out_error, LispContext ctx);
131 |
132 | // print out a lisp structure
133 | void lisp_print(Lisp l);
134 | void lisp_printf(FILE* file, Lisp l);
135 | const char* lisp_error_string(LispError error);
136 |
137 | // DATA STRUCTURES
138 | // -----------------------------------------
139 | #define lisp_type(x) ((x).type)
140 | #define lisp_eq(a, b) ((a).val.ptr_val == (b).val.ptr_val)
141 | int lisp_eq_r(Lisp a, Lisp b);
142 | Lisp lisp_make_null(void);
143 |
144 | #define lisp_is_null(x) ((x).type == LISP_NULL)
145 |
146 | Lisp lisp_make_int(int n);
147 | int lisp_int(Lisp x);
148 |
149 | Lisp lisp_make_real(float x);
150 | float lisp_real(Lisp x);
151 |
152 | Lisp lisp_make_string(const char* c_string, LispContext ctx);
153 | Lisp lisp_make_empty_string(unsigned int n, char c, LispContext ctx);
154 | char lisp_string_ref(Lisp s, int n);
155 | void lisp_string_set(Lisp s, int n, char c);
156 | char* lisp_string(Lisp s);
157 |
158 | Lisp lisp_make_char(int c);
159 | int lisp_char(Lisp l);
160 |
161 | Lisp lisp_make_symbol(const char* symbol, LispContext ctx);
162 | const char* lisp_symbol(Lisp x);
163 |
164 | Lisp lisp_car(Lisp p);
165 | Lisp lisp_cdr(Lisp p);
166 | void lisp_set_car(Lisp p, Lisp x);
167 | void lisp_set_cdr(Lisp p, Lisp x);
168 | Lisp lisp_cons(Lisp car, Lisp cdr, LispContext ctx);
169 | #define lisp_is_pair(p) ((p).type == LISP_PAIR)
170 |
171 | Lisp lisp_list_copy(Lisp x, LispContext ctx);
172 | Lisp lisp_make_list(Lisp x, int n, LispContext ctx);
173 | // convenience function for cons'ing together items. arguments must be null terminated
174 | Lisp lisp_make_listv(LispContext ctx, Lisp first, ...);
175 | // another helpful list building technique O(1)
176 | void lisp_fast_append(Lisp* front, Lisp* back, Lisp x, LispContext ctx);
177 | Lisp lisp_list_append(Lisp l, Lisp tail, LispContext ctx); // O(n)
178 | Lisp lisp_list_advance(Lisp l, int i); // O(n)
179 | Lisp lisp_list_ref(Lisp l, int i); // O(n)
180 | int lisp_list_index_of(Lisp l, Lisp x); // O(n)
181 | int lisp_list_length(Lisp l); // O(n)
182 | // given a list of pairs ((key1 val1) (key2 val2) ... (keyN valN))
183 | // returns the pair with the given key or null of none
184 | Lisp lisp_list_assoc(Lisp l, Lisp key); // O(n)
185 | // given a list of pairs returns the value of the pair with the given key. (car (cdr (assoc ..)))
186 | Lisp lisp_list_for_key(Lisp l, Lisp key); // O(n)
187 | // concise CAR/CDR combos such as CADR, CAAADR, CAAADAAR....
188 | Lisp lisp_list_nav(Lisp p, const char* path);
189 | // This operation modifys the list
190 | Lisp lisp_list_reverse(Lisp l); // O(n)
191 |
192 | Lisp lisp_make_vector(unsigned int n, Lisp x, LispContext ctx);
193 | int lisp_vector_length(Lisp v);
194 | Lisp lisp_vector_ref(Lisp v, int i);
195 | void lisp_vector_set(Lisp v, int i, Lisp x);
196 | Lisp lisp_vector_assoc(Lisp v, Lisp key); // O(n)
197 | Lisp lisp_vector_grow(Lisp v, unsigned int n, LispContext ctx);
198 | Lisp lisp_subvector(Lisp old, int start, int end, LispContext ctx);
199 |
200 | Lisp lisp_make_table(unsigned int capacity, LispContext ctx);
201 | void lisp_table_set(Lisp t, Lisp key, Lisp x, LispContext ctx);
202 | // returns the key value pair, or null if not found
203 | Lisp lisp_table_get(Lisp t, Lisp key, LispContext ctx);
204 | unsigned int lisp_table_size(Lisp t);
205 | Lisp lisp_table_to_assoc_list(Lisp t, LispContext ctx);
206 |
207 | /* This struct is just for making definitions a little less error prone,
208 | having separate arrays for names and functions leads to easy mistakes. */
209 | typedef struct
210 | {
211 | const char* name;
212 | LispCFunc func_ptr;
213 | } LispFuncDef;
214 | void lisp_table_define_funcs(Lisp t, const LispFuncDef* defs, LispContext ctx);
215 |
216 | // programatically generate compound procedures
217 | Lisp lisp_make_lambda(Lisp args, Lisp body, Lisp env, LispContext ctx);
218 |
219 | // C functions
220 | Lisp lisp_make_func(LispCFunc func_ptr);
221 | LispCFunc lisp_func(Lisp l);
222 |
223 | // evaluation environments
224 | Lisp lisp_env_global(LispContext ctx);
225 | void lisp_env_set_global(Lisp env, LispContext ctx);
226 |
227 | Lisp lisp_env_extend(Lisp l, Lisp table, LispContext ctx);
228 | Lisp lisp_env_lookup(Lisp l, Lisp key, LispContext ctx);
229 | void lisp_env_define(Lisp l, Lisp key, Lisp x, LispContext ctx);
230 | void lisp_env_set(Lisp l, Lisp key, Lisp x, LispContext ctx);
231 |
232 | #endif
233 |
--------------------------------------------------------------------------------
/NtLisp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29709.97
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LispLib", "LispLib\LispLib.vcxproj", "{71FC9FC1-F46F-41D4-913E-07298D6E8220}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NtLispRepl", "NtLispRepl\NtLispRepl.vcxproj", "{82B12053-4DA0-440B-8AF4-55F49658299E}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NtLisp", "NtLisp\NtLisp.vcxproj", "{7FAC530A-63E4-4C27-86E1-B318205E4C0E}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|x64 = Debug|x64
15 | Debug|x86 = Debug|x86
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x64.ActiveCfg = Debug|x64
21 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x64.Build.0 = Debug|x64
22 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x64.Deploy.0 = Debug|x64
23 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x86.ActiveCfg = Debug|Win32
24 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x86.Build.0 = Debug|Win32
25 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Debug|x86.Deploy.0 = Debug|Win32
26 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x64.ActiveCfg = Release|x64
27 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x64.Build.0 = Release|x64
28 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x64.Deploy.0 = Release|x64
29 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x86.ActiveCfg = Release|Win32
30 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x86.Build.0 = Release|Win32
31 | {71FC9FC1-F46F-41D4-913E-07298D6E8220}.Release|x86.Deploy.0 = Release|Win32
32 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Debug|x64.ActiveCfg = Debug|x64
33 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Debug|x64.Build.0 = Debug|x64
34 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Debug|x86.ActiveCfg = Debug|Win32
35 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Debug|x86.Build.0 = Debug|Win32
36 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Release|x64.ActiveCfg = Release|x64
37 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Release|x64.Build.0 = Release|x64
38 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Release|x86.ActiveCfg = Release|Win32
39 | {82B12053-4DA0-440B-8AF4-55F49658299E}.Release|x86.Build.0 = Release|Win32
40 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x64.ActiveCfg = Debug|x64
41 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x64.Build.0 = Debug|x64
42 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x64.Deploy.0 = Debug|x64
43 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x86.ActiveCfg = Debug|Win32
44 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x86.Build.0 = Debug|Win32
45 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Debug|x86.Deploy.0 = Debug|Win32
46 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x64.ActiveCfg = Release|x64
47 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x64.Build.0 = Release|x64
48 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x64.Deploy.0 = Release|x64
49 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x86.ActiveCfg = Release|Win32
50 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x86.Build.0 = Release|Win32
51 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}.Release|x86.Deploy.0 = Release|Win32
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | GlobalSection(ExtensibilityGlobals) = postSolution
57 | SolutionGuid = {F86C24F0-ACB0-423E-9DBC-C1B65F86BC4A}
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/NtLisp/NtLisp.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {7FAC530A-63E4-4C27-86E1-B318205E4C0E}
23 | {1bc93793-694f-48fe-9372-81e2b05556fd}
24 | v4.5
25 | 12.0
26 | Debug
27 | Win32
28 | KernelLuaVm
29 | 10.0.19041.0
30 |
31 |
32 |
33 | Windows10
34 | true
35 | WindowsKernelModeDriver10.0
36 | Driver
37 | KMDF
38 | Universal
39 |
40 |
41 | Windows10
42 | false
43 | WindowsKernelModeDriver10.0
44 | Driver
45 | KMDF
46 | Universal
47 |
48 |
49 | Windows10
50 | true
51 | WindowsKernelModeDriver10.0
52 | Driver
53 | KMDF
54 | Universal
55 |
56 |
57 | Windows10
58 | false
59 | WindowsKernelModeDriver10.0
60 | Driver
61 | KMDF
62 | Universal
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | DbgengKernelDebugger
74 | $(SolutionDir)..\LispLib;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
75 |
76 |
77 | DbgengKernelDebugger
78 | $(SolutionDir)..\LispLib;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
79 |
80 |
81 | DbgengKernelDebugger
82 | $(SolutionDir)LispLib;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
83 |
84 |
85 | DbgengKernelDebugger
86 | $(SolutionDir)LispLib;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)
87 |
88 |
89 |
90 | false
91 | CompileAsCpp
92 | false
93 | false
94 | false
95 | stdcpp17
96 | _DEBUG;_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)
97 |
98 |
99 | false
100 |
101 |
102 |
103 |
104 | false
105 | CompileAsCpp
106 | false
107 | false
108 | stdcpp17
109 |
110 |
111 | false
112 |
113 |
114 |
115 |
116 | false
117 | CompileAsCpp
118 | false
119 | false
120 | false
121 | stdcpp17
122 | _DEBUG;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)
123 |
124 |
125 | false
126 |
127 |
128 |
129 |
130 | false
131 | CompileAsCpp
132 | false
133 | false
134 | stdcpp17
135 | /Oi- %(AdditionalOptions)
136 |
137 |
138 | false
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | {71fc9fc1-f46f-41d4-913e-07298d6e8220}
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 | CppCode
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
--------------------------------------------------------------------------------
/NtLisp/NtLisp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | crt\libmd
7 |
8 |
9 | crt\libmd
10 |
11 |
12 | crt\libmd
13 |
14 |
15 | crt\libmd
16 |
17 |
18 | crt\libmd
19 |
20 |
21 | crt\libmd
22 |
23 |
24 | crt\libmd
25 |
26 |
27 | crt\libmd
28 |
29 |
30 | crt\libmd
31 |
32 |
33 | crt\libmd
34 |
35 |
36 | crt\libmd
37 |
38 |
39 | crt\libmd
40 |
41 |
42 | crt\libmd
43 |
44 |
45 | crt\libmd
46 |
47 |
48 | crt\libmd
49 |
50 |
51 | crt\libmd
52 |
53 |
54 | crt\libmd
55 |
56 |
57 | crt\libmd
58 |
59 |
60 | crt\libmd
61 |
62 |
63 | crt\libmd
64 |
65 |
66 | crt\libmd
67 |
68 |
69 | crt\libmd
70 |
71 |
72 | crt\libmd
73 |
74 |
75 | crt\libmd
76 |
77 |
78 | crt\libmd
79 |
80 |
81 | crt\libmd
82 |
83 |
84 | crt\libmd
85 |
86 |
87 | crt\libmd
88 |
89 |
90 | crt\libmd
91 |
92 |
93 | crt\libmd
94 |
95 |
96 | crt\libmd
97 |
98 |
99 | crt\libmd
100 |
101 |
102 | crt\libmd
103 |
104 |
105 | crt\libmd
106 |
107 |
108 | crt\libmd
109 |
110 |
111 | crt\libmd
112 |
113 |
114 | crt\libmd
115 |
116 |
117 | crt\libmd
118 |
119 |
120 | crt\libmd
121 |
122 |
123 | crt\libmd
124 |
125 |
126 | crt\libmd
127 |
128 |
129 | crt\libmd
130 |
131 |
132 | crt\libmd
133 |
134 |
135 | crt\libmd
136 |
137 |
138 | crt\misc
139 |
140 |
141 | crt\misc
142 |
143 |
144 | crt\misc
145 |
146 |
147 | crt\misc
148 |
149 |
150 |
151 |
152 | {34fc80ff-2c2f-48ce-bc9d-e58bed8bd8c5}
153 |
154 |
155 | {d020440f-50cc-4ecd-bb74-30ed1469974b}
156 |
157 |
158 | {51d27d14-edb0-4590-bb60-8e20b89d3a8a}
159 |
160 |
161 |
162 |
163 | crt
164 |
165 |
166 | crt\misc
167 |
168 |
169 | crt\misc
170 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/NtLisp/crt/crt.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define _INC_STDIO
3 | #include
4 | #include
5 | #include
6 | #include "stdint.h"
7 | #include "libmd.h"
8 |
9 | #define FILE_STDOUT ((FILE*)0x13370001)
10 | #define FILE_STDERR ((FILE*)0x13370002)
11 |
12 | // CRT initializers.
13 | //
14 | #pragma section(".CRT", read)
15 | using fn_crt_initializer = void(*)();
16 | __declspec( allocate( ".CRT" ) ) static const fn_crt_initializer crt_tracker = nullptr;
17 |
18 | namespace crt
19 | {
20 | static void initialize()
21 | {
22 | const fn_crt_initializer* entry = &crt_tracker;
23 | while ( *++entry )
24 | ( *entry )( );
25 | }
26 | };
27 |
28 | // C++ memory decleration.
29 | //
30 | __declspec( restrict ) void* malloc( size_t n );
31 | void free( void* p );
32 | void* operator new( size_t, void* where );
33 | void* operator new( size_t Size );
34 | void* operator new[ ] ( size_t Size );
35 | void operator delete( void* Adr );
36 | void operator delete( void* Adr, size_t Size );
37 | void operator delete[ ] ( void* Adr );
38 | void operator delete[ ] ( void* Adr, size_t Size );
39 |
40 | extern "C"
41 | {
42 | // String utils.
43 | //
44 | int isalpha( int c );
45 | int isdigit( int c );
46 | int isalnum( int c );
47 | int iscntrl( int c );
48 | int isgraph( int c );
49 | int ispunct( int c );
50 | __declspec( dllimport ) int sscanf_s( const char* buffer, const char* format, ... ); // @ ntoskrnl.lib
51 | __declspec( dllimport ) int sprintf_s( char* buffer, size_t sizeOfBuffer, const char* format, ... ); // @ ntoskrnl.lib
52 | double strtod( const char* str, const char** endptr );
53 | char* strpbrk( const char* s1, const char* s2 );
54 | int strcoll( const char* a, const char* b );
55 |
56 | // IO utils.
57 | //
58 | typedef struct _FILE {} FILE; // Maybe it will be implemented one day.
59 |
60 | FILE* __cdecl __acrt_iob_func( unsigned i );
61 | FILE* freopen( const char* filename, const char* mode, FILE* stream );
62 | size_t fwrite( const void* ptr, size_t size, size_t count, FILE* stream );
63 | size_t fread( void* ptr, size_t size, size_t count, FILE* stream );
64 | int getc( FILE* stream );
65 | FILE* fopen( const char* filename, const char* mode );
66 | int fflush( FILE* stream );
67 | int ferror( FILE* stream );
68 | int feof( FILE* stream );
69 | int fclose( FILE* stream );
70 | int fprintf( FILE* stream, const char* fmt, ... );
71 |
72 | // Misc. functions.
73 | //
74 | void abort();
75 | char* getenv();
76 | };
--------------------------------------------------------------------------------
/NtLisp/crt/io.c:
--------------------------------------------------------------------------------
1 | #include "../logger.hpp"
2 | #include "crt.h"
3 |
4 | FILE* __cdecl __acrt_iob_func( unsigned i )
5 | {
6 | if ( i == 1 ) return FILE_STDOUT;
7 | if ( i == 2 ) return FILE_STDERR;
8 | return 0;
9 | }
10 |
11 | FILE* freopen( const char* filename, const char* mode, FILE* stream )
12 | {
13 | return 0;
14 | }
15 |
16 | size_t fwrite( const void* ptr, size_t size, size_t count, FILE* stream )
17 | {
18 | if ( stream == FILE_STDOUT )
19 | {
20 | logger::logs.append( ptr, size * count );
21 | return count;
22 | }
23 | else if ( stream == FILE_STDERR )
24 | {
25 | logger::errors.append( ptr, size * count );
26 | return count;
27 | }
28 | return 0;
29 | }
30 |
31 | size_t fread( void* ptr, size_t size, size_t count, FILE* stream )
32 | {
33 | return 0;
34 | }
35 |
36 | int getc( FILE* stream )
37 | {
38 | return -1;
39 | }
40 |
41 | FILE* fopen( const char* filename, const char* mode )
42 | {
43 | return 0;
44 | }
45 |
46 | int fflush( FILE* stream )
47 | {
48 | return 0;
49 | }
50 |
51 | int ferror( FILE* stream )
52 | {
53 | return 1;
54 | }
55 |
56 | int feof( FILE* stream )
57 | {
58 | return 1;
59 | }
60 |
61 | int fclose( FILE* stream )
62 | {
63 | return 1;
64 | }
65 |
66 | #include
67 |
68 | extern "C" __declspec(dllimport) int _vsnprintf( char* dest, size_t count, const char* fmt, va_list args );
69 |
70 | int fprintf( FILE* stream, const char* fmt, ... )
71 | {
72 | va_list args;
73 | va_start( args, fmt );
74 | char buf[512] = "";
75 | auto n = _vsnprintf( buf, sizeof( buf ), fmt, args );
76 | if ( n >= sizeof(buf) )
77 | {
78 | // todo: allocate things
79 | __debugbreak();
80 | }
81 | va_end( args );
82 | fwrite( buf, n, 1, stream );
83 | return 1;
84 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include "stdint.h"
4 |
5 | extern "C"
6 | {
7 | extern char _fltused;
8 |
9 | typedef double double_t;
10 | typedef float float_t;
11 |
12 | #define FLT_EVAL_METHOD 0
13 |
14 | #ifndef _HUGE_ENUF
15 | #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
16 | #endif
17 |
18 | #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
19 | #define HUGE_VAL ((double)INFINITY)
20 | #define HUGE_VALF ((float)INFINITY)
21 | #define HUGE_VALL ((long double)INFINITY)
22 | #define NAN ((float)(INFINITY * 0.0F))
23 |
24 | #define _DENORM (-2)
25 | #define _FINITE (-1)
26 | #define _INFCODE 1
27 | #define _NANCODE 2
28 |
29 | #define FP_INFINITE _INFCODE
30 | #define FP_NAN _NANCODE
31 | #define FP_NORMAL _FINITE
32 | #define FP_SUBNORMAL _DENORM
33 | #define FP_ZERO 0
34 |
35 | #define isinf(x) (fpclassify(x)==FP_INFINITE)
36 | #define isnan(x) (fpclassify(x)==FP_NAN)
37 | #define isfinite(x) (fpclassify(x)!=FP_NAN && fpclassify(x)!=FP_INFINITE )
38 | #define isnormal(x) (fpclassify(x)==FP_NORMAL)
39 |
40 |
41 | #define _C2 1 // 0 if not 2's complement
42 | #define FP_ILOGB0 (-0x7fffffff - _C2)
43 | #define FP_ILOGBNAN 0x7fffffff
44 |
45 | #define MATH_ERRNO 1
46 | #define MATH_ERREXCEPT 2
47 | #define math_errhandling (MATH_ERRNO | MATH_ERREXCEPT)
48 |
49 | // Values for use as arguments to the _fperrraise function
50 | #define _FE_DIVBYZERO 0x04
51 | #define _FE_INEXACT 0x20
52 | #define _FE_INVALID 0x01
53 | #define _FE_OVERFLOW 0x08
54 | #define _FE_UNDERFLOW 0x10
55 |
56 | #define _D0_C 3 // little-endian, small long doubles
57 | #define _D1_C 2
58 | #define _D2_C 1
59 | #define _D3_C 0
60 |
61 | #define _DBIAS 0x3fe
62 | #define _DOFF 4
63 |
64 | #define _F0_C 1 // little-endian
65 | #define _F1_C 0
66 |
67 | #define _FBIAS 0x7e
68 | #define _FOFF 7
69 | #define _FRND 1
70 |
71 | #define _L0_C 3 // little-endian, 64-bit long doubles
72 | #define _L1_C 2
73 | #define _L2_C 1
74 | #define _L3_C 0
75 |
76 | #define _LBIAS 0x3fe
77 | #define _LOFF 4
78 |
79 | // IEEE 754 double properties
80 | #define _DFRAC ((unsigned short)((1 << _DOFF) - 1))
81 | #define _DMASK ((unsigned short)(0x7fff & ~_DFRAC))
82 | #define _DMAX ((unsigned short)((1 << (15 - _DOFF)) - 1))
83 | #define _DSIGN ((unsigned short)0x8000)
84 |
85 | // IEEE 754 float properties
86 | #define _FFRAC ((unsigned short)((1 << _FOFF) - 1))
87 | #define _FMASK ((unsigned short)(0x7fff & ~_FFRAC))
88 | #define _FMAX ((unsigned short)((1 << (15 - _FOFF)) - 1))
89 | #define _FSIGN ((unsigned short)0x8000)
90 |
91 | // IEEE 754 long double properties
92 | #define _LFRAC ((unsigned short)(-1))
93 | #define _LMASK ((unsigned short)0x7fff)
94 | #define _LMAX ((unsigned short)0x7fff)
95 | #define _LSIGN ((unsigned short)0x8000)
96 |
97 | #define _DHUGE_EXP (int)(_DMAX * 900L / 1000)
98 | #define _FHUGE_EXP (int)(_FMAX * 900L / 1000)
99 | #define _LHUGE_EXP (int)(_LMAX * 900L / 1000)
100 |
101 | #define _DSIGN_C(_Val) (((_double_val *)(char*)&(_Val))->_Sh[_D0_C] & _DSIGN)
102 | #define _FSIGN_C(_Val) (((_float_val *)(char*)&(_Val))->_Sh[_F0_C] & _FSIGN)
103 | #define _LSIGN_C(_Val) (((_ldouble_val*)(char*)&(_Val))->_Sh[_L0_C] & _LSIGN)
104 |
105 |
106 | #define FORCE_EVAL(x) do { \
107 | if (sizeof(x) == sizeof(float)) { \
108 | volatile float __x; \
109 | __x = (x); \
110 | (void)__x; \
111 | } else if (sizeof(x) == sizeof(double)) { \
112 | volatile double __x; \
113 | __x = (x); \
114 | (void)__x; \
115 | } else { \
116 | volatile long double __x; \
117 | __x = (x); \
118 | (void)__x; \
119 | } \
120 | } while(0)
121 |
122 | /* Get two 32 bit ints from a double. */
123 | #define EXTRACT_WORDS(hi,lo,d) \
124 | do { \
125 | union {double f; uint64_t i;} __u; \
126 | __u.f = (d); \
127 | (hi) = __u.i >> 32; \
128 | (lo) = (uint32_t)__u.i; \
129 | } while (0)
130 |
131 | /* Get the more significant 32 bit int from a double. */
132 | #define GET_HIGH_WORD(hi,d) \
133 | do { \
134 | union {double f; uint64_t i;} __u; \
135 | __u.f = (d); \
136 | (hi) = __u.i >> 32; \
137 | } while (0)
138 |
139 | /* Get the less significant 32 bit int from a double. */
140 | #define GET_LOW_WORD(lo,d) \
141 | do { \
142 | union {double f; uint64_t i;} __u; \
143 | __u.f = (d); \
144 | (lo) = (uint32_t)__u.i; \
145 | } while (0)
146 |
147 | /* Set a double from two 32 bit ints. */
148 | #define INSERT_WORDS(d,hi,lo) \
149 | do { \
150 | union {double f; uint64_t i;} __u; \
151 | __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \
152 | (d) = __u.f; \
153 | } while (0)
154 |
155 | /* Set the more significant 32 bits of a double from an int. */
156 | #define SET_HIGH_WORD(d,hi) \
157 | do { \
158 | union {double f; uint64_t i;} __u; \
159 | __u.f = (d); \
160 | __u.i &= 0xffffffff; \
161 | __u.i |= (uint64_t)(hi) << 32; \
162 | (d) = __u.f; \
163 | } while (0)
164 |
165 | /* Set the less significant 32 bits of a double from an int. */
166 | #define SET_LOW_WORD(d,lo) \
167 | do { \
168 | union {double f; uint64_t i;} __u; \
169 | __u.f = (d); \
170 | __u.i &= 0xffffffff00000000ull; \
171 | __u.i |= (uint32_t)(lo); \
172 | (d) = __u.f; \
173 | } while (0)
174 |
175 | #define DBL_EPSILON 2.22044604925031308085e-16
176 |
177 | double trunc( double x );
178 | double tgamma( double x );
179 | double __lgamma_r( double x, int* sign );
180 | double sqrt( double x );
181 | double tanh( double x );
182 | double tan( double x );
183 | double sinh( double x );
184 | double sin( double x );
185 | double cosh( double x );
186 | double cos( double x );
187 | double atanh( double x );
188 | double atan( double x );
189 | double asinh( double x );
190 | double asin( double x );
191 | double acosh( double x );
192 | double acos( double x );
193 | double atan2( double y, double x );
194 | double scalbn( double x, int n );
195 | double rint( double x );
196 | double pow( double x, double y );
197 | double nearbyint( double x );
198 | double modf( double x, double* iptr );
199 | double log( double x );
200 | double log1p( double x );
201 | double log10( double x );
202 | double lgamma( double x );
203 | double ldexp( double x, int n );
204 | double frexp( double x, int* e );
205 | double fmod( double x, double y );
206 | double floor( double x );
207 | double expm1( double x );
208 | double exp( double x );
209 | double erf( double x );
210 | double copysign( double x, double y );
211 | double ceil( double x );
212 | double __tan( double x, double y, int odd );
213 | double __sin( double x, double y, int iy );
214 | int signbit( double x );
215 | int __rem_pio2_large( double* x, double* y, int e0, int nx, int prec );
216 | int __rem_pio2( double x, double* y );
217 | int fpclassify( double x );
218 | double __expo2( double x );
219 | double __cos( double x, double y );
220 | double fabs( double x );
221 | };
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__cos.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /*
13 | * __cos( x, y )
14 | * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
15 | * Input x is assumed to be bounded by ~pi/4 in magnitude.
16 | * Input y is the tail of x.
17 | *
18 | * Algorithm
19 | * 1. Since cos(-x) = cos(x), we need only to consider positive x.
20 | * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
21 | * 3. cos(x) is approximated by a polynomial of degree 14 on
22 | * [0,pi/4]
23 | * 4 14
24 | * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
25 | * where the remez error is
26 | *
27 | * | 2 4 6 8 10 12 14 | -58
28 | * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
29 | * | |
30 | *
31 | * 4 6 8 10 12 14
32 | * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
33 | * cos(x) ~ 1 - x*x/2 + r
34 | * since cos(x+y) ~ cos(x) - sin(x)*y
35 | * ~ cos(x) - x*y,
36 | * a correction term is necessary in cos(x) and hence
37 | * cos(x+y) = 1 - (x*x/2 - (r - x*y))
38 | * For better accuracy, rearrange to
39 | * cos(x+y) ~ w + (tmp + (r-x*y))
40 | * where w = 1 - x*x/2 and tmp is a tiny correction term
41 | * (1 - x*x/2 == w + tmp exactly in infinite precision).
42 | * The exactness of w + tmp in infinite precision depends on w
43 | * and tmp having the same precision as x. If they have extra
44 | * precision due to compiler bugs, then the extra precision is
45 | * only good provided it is retained in all terms of the final
46 | * expression for cos(). Retention happens in all cases tested
47 | * under FreeBSD, so don't pessimize things by forcibly clipping
48 | * any extra precision in w.
49 | */
50 |
51 | #include "..\libmd.h"
52 |
53 | static const double
54 | C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
55 | C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
56 | C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
57 | C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
58 | C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
59 | C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
60 |
61 | double __cos(double x, double y)
62 | {
63 | double_t hz,z,r,w;
64 |
65 | z = x*x;
66 | w = z*z;
67 | r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6));
68 | hz = 0.5*z;
69 | w = 1.0-hz;
70 | return w + (((1.0-w)-hz) + (z*r-x*y));
71 | }
72 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__expo2.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */
4 | static const int k = 2043;
5 | static const double kln2 = 0x1.62066151add8bp+10;
6 |
7 | /* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
8 | double __expo2(double x)
9 | {
10 | double scale;
11 |
12 | /* note that k is odd and scale*scale overflows */
13 | INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0);
14 | /* exp(x - k ln2) * 2**(k-1) */
15 | return exp(x - kln2) * scale * scale;
16 | }
17 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__rem_pio2.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | *
12 | * Optimized by Bruce D. Evans.
13 | */
14 | /* __rem_pio2(x,y)
15 | *
16 | * return the remainder of x rem pi/2 in y[0]+y[1]
17 | * use __rem_pio2_large() for large x
18 | */
19 |
20 | #include "..\libmd.h"
21 |
22 | #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
23 | #define EPS DBL_EPSILON
24 | #elif FLT_EVAL_METHOD==2
25 | #define EPS LDBL_EPSILON
26 | #endif
27 |
28 | /*
29 | * invpio2: 53 bits of 2/pi
30 | * pio2_1: first 33 bit of pi/2
31 | * pio2_1t: pi/2 - pio2_1
32 | * pio2_2: second 33 bit of pi/2
33 | * pio2_2t: pi/2 - (pio2_1+pio2_2)
34 | * pio2_3: third 33 bit of pi/2
35 | * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
36 | */
37 | static const double
38 | toint = 1.5/EPS,
39 | invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
40 | pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
41 | pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
42 | pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
43 | pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
44 | pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
45 | pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
46 |
47 | /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */
48 | int __rem_pio2(double x, double *y)
49 | {
50 | union {double f; uint64_t i;} u = {x};
51 | double_t z,w,t,r,fn;
52 | double tx[3],ty[2];
53 | uint32_t ix;
54 | int sign, n, ex, ey, i;
55 |
56 | sign = u.i>>63;
57 | ix = u.i>>32 & 0x7fffffff;
58 | if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
59 | if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
60 | goto medium; /* cancellation -- use medium case */
61 | if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */
62 | if (!sign) {
63 | z = x - pio2_1; /* one round good to 85 bits */
64 | y[0] = z - pio2_1t;
65 | y[1] = (z-y[0]) - pio2_1t;
66 | return 1;
67 | } else {
68 | z = x + pio2_1;
69 | y[0] = z + pio2_1t;
70 | y[1] = (z-y[0]) + pio2_1t;
71 | return -1;
72 | }
73 | } else {
74 | if (!sign) {
75 | z = x - 2*pio2_1;
76 | y[0] = z - 2*pio2_1t;
77 | y[1] = (z-y[0]) - 2*pio2_1t;
78 | return 2;
79 | } else {
80 | z = x + 2*pio2_1;
81 | y[0] = z + 2*pio2_1t;
82 | y[1] = (z-y[0]) + 2*pio2_1t;
83 | return -2;
84 | }
85 | }
86 | }
87 | if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */
88 | if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
89 | if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */
90 | goto medium;
91 | if (!sign) {
92 | z = x - 3*pio2_1;
93 | y[0] = z - 3*pio2_1t;
94 | y[1] = (z-y[0]) - 3*pio2_1t;
95 | return 3;
96 | } else {
97 | z = x + 3*pio2_1;
98 | y[0] = z + 3*pio2_1t;
99 | y[1] = (z-y[0]) + 3*pio2_1t;
100 | return -3;
101 | }
102 | } else {
103 | if (ix == 0x401921fb) /* |x| ~= 4pi/2 */
104 | goto medium;
105 | if (!sign) {
106 | z = x - 4*pio2_1;
107 | y[0] = z - 4*pio2_1t;
108 | y[1] = (z-y[0]) - 4*pio2_1t;
109 | return 4;
110 | } else {
111 | z = x + 4*pio2_1;
112 | y[0] = z + 4*pio2_1t;
113 | y[1] = (z-y[0]) + 4*pio2_1t;
114 | return -4;
115 | }
116 | }
117 | }
118 | if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
119 | medium:
120 | /* rint(x/(pi/2)), Assume round-to-nearest. */
121 | fn = (double_t)x*invpio2 + toint - toint;
122 | n = (int32_t)fn;
123 | r = x - fn*pio2_1;
124 | w = fn*pio2_1t; /* 1st round, good to 85 bits */
125 | y[0] = r - w;
126 | u.f = y[0];
127 | ey = u.i>>52 & 0x7ff;
128 | ex = ix>>20;
129 | if (ex - ey > 16) { /* 2nd round, good to 118 bits */
130 | t = r;
131 | w = fn*pio2_2;
132 | r = t - w;
133 | w = fn*pio2_2t - ((t-r)-w);
134 | y[0] = r - w;
135 | u.f = y[0];
136 | ey = u.i>>52 & 0x7ff;
137 | if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */
138 | t = r;
139 | w = fn*pio2_3;
140 | r = t - w;
141 | w = fn*pio2_3t - ((t-r)-w);
142 | y[0] = r - w;
143 | }
144 | }
145 | y[1] = (r - y[0]) - w;
146 | return n;
147 | }
148 | /*
149 | * all other (large) arguments
150 | */
151 | if (ix >= 0x7ff00000) { /* x is inf or NaN */
152 | y[0] = y[1] = x - x;
153 | return 0;
154 | }
155 | /* set z = scalbn(|x|,-ilogb(x)+23) */
156 | u.f = x;
157 | u.i &= (uint64_t)-1>>12;
158 | u.i |= (uint64_t)(0x3ff + 23)<<52;
159 | z = u.f;
160 | for (i=0; i < 2; i++) {
161 | tx[i] = (double)(int32_t)z;
162 | z = (z-tx[i])*0x1p24;
163 | }
164 | tx[i] = z;
165 | /* skip zero terms, first term is non-zero */
166 | while (tx[i] == 0.0)
167 | i--;
168 | n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1);
169 | if (sign) {
170 | y[0] = -ty[0];
171 | y[1] = -ty[1];
172 | return -n;
173 | }
174 | y[0] = ty[0];
175 | y[1] = ty[1];
176 | return n;
177 | }
178 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__rem_pio2_large.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /*
13 | * __rem_pio2_large(x,y,e0,nx,prec)
14 | * double x[],y[]; int e0,nx,prec;
15 | *
16 | * __rem_pio2_large return the last three digits of N with
17 | * y = x - N*pi/2
18 | * so that |y| < pi/2.
19 | *
20 | * The method is to compute the integer (mod 8) and fraction parts of
21 | * (2/pi)*x without doing the full multiplication. In general we
22 | * skip the part of the product that are known to be a huge integer (
23 | * more accurately, = 0 mod 8 ). Thus the number of operations are
24 | * independent of the exponent of the input.
25 | *
26 | * (2/pi) is represented by an array of 24-bit integers in ipio2[].
27 | *
28 | * Input parameters:
29 | * x[] The input value (must be positive) is broken into nx
30 | * pieces of 24-bit integers in double precision format.
31 | * x[i] will be the i-th 24 bit of x. The scaled exponent
32 | * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
33 | * match x's up to 24 bits.
34 | *
35 | * Example of breaking a double positive z into x[0]+x[1]+x[2]:
36 | * e0 = ilogb(z)-23
37 | * z = scalbn(z,-e0)
38 | * for i = 0,1,2
39 | * x[i] = floor(z)
40 | * z = (z-x[i])*2**24
41 | *
42 | *
43 | * y[] ouput result in an array of double precision numbers.
44 | * The dimension of y[] is:
45 | * 24-bit precision 1
46 | * 53-bit precision 2
47 | * 64-bit precision 2
48 | * 113-bit precision 3
49 | * The actual value is the sum of them. Thus for 113-bit
50 | * precison, one may have to do something like:
51 | *
52 | * long double t,w,r_head, r_tail;
53 | * t = (long double)y[2] + (long double)y[1];
54 | * w = (long double)y[0];
55 | * r_head = t+w;
56 | * r_tail = w - (r_head - t);
57 | *
58 | * e0 The exponent of x[0]. Must be <= 16360 or you need to
59 | * expand the ipio2 table.
60 | *
61 | * nx dimension of x[]
62 | *
63 | * prec an integer indicating the precision:
64 | * 0 24 bits (single)
65 | * 1 53 bits (double)
66 | * 2 64 bits (extended)
67 | * 3 113 bits (quad)
68 | *
69 | * External function:
70 | * double scalbn(), floor();
71 | *
72 | *
73 | * Here is the description of some local variables:
74 | *
75 | * jk jk+1 is the initial number of terms of ipio2[] needed
76 | * in the computation. The minimum and recommended value
77 | * for jk is 3,4,4,6 for single, double, extended, and quad.
78 | * jk+1 must be 2 larger than you might expect so that our
79 | * recomputation test works. (Up to 24 bits in the integer
80 | * part (the 24 bits of it that we compute) and 23 bits in
81 | * the fraction part may be lost to cancelation before we
82 | * recompute.)
83 | *
84 | * jz local integer variable indicating the number of
85 | * terms of ipio2[] used.
86 | *
87 | * jx nx - 1
88 | *
89 | * jv index for pointing to the suitable ipio2[] for the
90 | * computation. In general, we want
91 | * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
92 | * is an integer. Thus
93 | * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
94 | * Hence jv = max(0,(e0-3)/24).
95 | *
96 | * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
97 | *
98 | * q[] double array with integral value, representing the
99 | * 24-bits chunk of the product of x and 2/pi.
100 | *
101 | * q0 the corresponding exponent of q[0]. Note that the
102 | * exponent for q[i] would be q0-24*i.
103 | *
104 | * PIo2[] double precision array, obtained by cutting pi/2
105 | * into 24 bits chunks.
106 | *
107 | * f[] ipio2[] in floating point
108 | *
109 | * iq[] integer array by breaking up q[] in 24-bits chunk.
110 | *
111 | * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
112 | *
113 | * ih integer. If >0 it indicates q[] is >= 0.5, hence
114 | * it also indicates the *sign* of the result.
115 | *
116 | */
117 | /*
118 | * Constants:
119 | * The hexadecimal values are the intended ones for the following
120 | * constants. The decimal values may be used, provided that the
121 | * compiler will convert from decimal to binary accurately enough
122 | * to produce the hexadecimal values shown.
123 | */
124 |
125 | #include "..\libmd.h"
126 |
127 | static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
128 |
129 | /*
130 | * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
131 | *
132 | * integer array, contains the (24*i)-th to (24*i+23)-th
133 | * bit of 2/pi after binary point. The corresponding
134 | * floating value is
135 | *
136 | * ipio2[i] * 2^(-24(i+1)).
137 | *
138 | * NB: This table must have at least (e0-3)/24 + jk terms.
139 | * For quad precision (e0 <= 16360, jk = 6), this is 686.
140 | */
141 | static const int32_t ipio2[] = {
142 | 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
143 | 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
144 | 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
145 | 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
146 | 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
147 | 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
148 | 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
149 | 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
150 | 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
151 | 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
152 | 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
153 |
154 | #if LDBL_MAX_EXP > 1024
155 | 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6,
156 | 0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2,
157 | 0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35,
158 | 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30,
159 | 0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C,
160 | 0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4,
161 | 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770,
162 | 0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7,
163 | 0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19,
164 | 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522,
165 | 0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16,
166 | 0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6,
167 | 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E,
168 | 0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48,
169 | 0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3,
170 | 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF,
171 | 0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55,
172 | 0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612,
173 | 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929,
174 | 0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC,
175 | 0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B,
176 | 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C,
177 | 0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4,
178 | 0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB,
179 | 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC,
180 | 0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C,
181 | 0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F,
182 | 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5,
183 | 0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437,
184 | 0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B,
185 | 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA,
186 | 0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD,
187 | 0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3,
188 | 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3,
189 | 0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717,
190 | 0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F,
191 | 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61,
192 | 0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB,
193 | 0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51,
194 | 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0,
195 | 0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C,
196 | 0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6,
197 | 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC,
198 | 0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED,
199 | 0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328,
200 | 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D,
201 | 0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0,
202 | 0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B,
203 | 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4,
204 | 0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3,
205 | 0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F,
206 | 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD,
207 | 0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B,
208 | 0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4,
209 | 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761,
210 | 0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31,
211 | 0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30,
212 | 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262,
213 | 0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E,
214 | 0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1,
215 | 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C,
216 | 0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4,
217 | 0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08,
218 | 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196,
219 | 0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9,
220 | 0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4,
221 | 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC,
222 | 0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C,
223 | 0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0,
224 | 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C,
225 | 0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0,
226 | 0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC,
227 | 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22,
228 | 0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893,
229 | 0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7,
230 | 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5,
231 | 0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F,
232 | 0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4,
233 | 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF,
234 | 0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B,
235 | 0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2,
236 | 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138,
237 | 0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E,
238 | 0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569,
239 | 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34,
240 | 0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9,
241 | 0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D,
242 | 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F,
243 | 0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855,
244 | 0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569,
245 | 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B,
246 | 0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE,
247 | 0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41,
248 | 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49,
249 | 0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F,
250 | 0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110,
251 | 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8,
252 | 0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365,
253 | 0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A,
254 | 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270,
255 | 0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5,
256 | 0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616,
257 | 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B,
258 | 0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0,
259 | #endif
260 | };
261 |
262 | static const double PIo2[] = {
263 | 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
264 | 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
265 | 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
266 | 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
267 | 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
268 | 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
269 | 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
270 | 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
271 | };
272 |
273 | int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec)
274 | {
275 | int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
276 | double z,fw,f[20],fq[20],q[20];
277 |
278 | /* initialize jk*/
279 | jk = init_jk[prec];
280 | jp = jk;
281 |
282 | /* determine jx,jv,q0, note that 3>q0 */
283 | jx = nx-1;
284 | jv = (e0-3)/24; if(jv<0) jv=0;
285 | q0 = e0-24*(jv+1);
286 |
287 | /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
288 | j = jv-jx; m = jx+jk;
289 | for (i=0; i<=m; i++,j++)
290 | f[i] = j<0 ? 0.0 : (double)ipio2[j];
291 |
292 | /* compute q[0],q[1],...q[jk] */
293 | for (i=0; i<=jk; i++) {
294 | for (j=0,fw=0.0; j<=jx; j++)
295 | fw += x[j]*f[jx+i-j];
296 | q[i] = fw;
297 | }
298 |
299 | jz = jk;
300 | recompute:
301 | /* distill q[] into iq[] reversingly */
302 | for (i=0,j=jz,z=q[jz]; j>0; i++,j--) {
303 | fw = (double)(int32_t)(0x1p-24*z);
304 | iq[i] = (int32_t)(z - 0x1p24*fw);
305 | z = q[j-1]+fw;
306 | }
307 |
308 | /* compute n */
309 | z = scalbn(z,q0); /* actual value of z */
310 | z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
311 | n = (int32_t)z;
312 | z -= (double)n;
313 | ih = 0;
314 | if (q0 > 0) { /* need iq[jz-1] to determine n */
315 | i = iq[jz-1]>>(24-q0); n += i;
316 | iq[jz-1] -= i<<(24-q0);
317 | ih = iq[jz-1]>>(23-q0);
318 | }
319 | else if (q0 == 0) ih = iq[jz-1]>>23;
320 | else if (z >= 0.5) ih = 2;
321 |
322 | if (ih > 0) { /* q > 0.5 */
323 | n += 1; carry = 0;
324 | for (i=0; i 0) { /* rare case: chance is 1 in 12 */
335 | switch(q0) {
336 | case 1:
337 | iq[jz-1] &= 0x7fffff; break;
338 | case 2:
339 | iq[jz-1] &= 0x3fffff; break;
340 | }
341 | }
342 | if (ih == 2) {
343 | z = 1.0 - z;
344 | if (carry != 0)
345 | z -= scalbn(1.0,q0);
346 | }
347 | }
348 |
349 | /* check if recomputation is needed */
350 | if (z == 0.0) {
351 | j = 0;
352 | for (i=jz-1; i>=jk; i--) j |= iq[i];
353 | if (j == 0) { /* need recomputation */
354 | for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */
355 |
356 | for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */
357 | f[jx+i] = (double)ipio2[jv+i];
358 | for (j=0,fw=0.0; j<=jx; j++)
359 | fw += x[j]*f[jx+i-j];
360 | q[i] = fw;
361 | }
362 | jz += k;
363 | goto recompute;
364 | }
365 | }
366 |
367 | /* chop off zero terms */
368 | if (z == 0.0) {
369 | jz -= 1;
370 | q0 -= 24;
371 | while (iq[jz] == 0) {
372 | jz--;
373 | q0 -= 24;
374 | }
375 | } else { /* break z into 24-bit if necessary */
376 | z = scalbn(z,-q0);
377 | if (z >= 0x1p24) {
378 | fw = (double)(int32_t)(0x1p-24*z);
379 | iq[jz] = (int32_t)(z - 0x1p24*fw);
380 | jz += 1;
381 | q0 += 24;
382 | iq[jz] = (int32_t)fw;
383 | } else
384 | iq[jz] = (int32_t)z;
385 | }
386 |
387 | /* convert integer "bit" chunk to floating-point value */
388 | fw = scalbn(1.0,q0);
389 | for (i=jz; i>=0; i--) {
390 | q[i] = fw*(double)iq[i];
391 | fw *= 0x1p-24;
392 | }
393 |
394 | /* compute PIo2[0,...,jp]*q[jz,...,0] */
395 | for(i=jz; i>=0; i--) {
396 | for (fw=0.0,k=0; k<=jp && k<=jz-i; k++)
397 | fw += PIo2[k]*q[i+k];
398 | fq[jz-i] = fw;
399 | }
400 |
401 | /* compress fq[] into y[] */
402 | switch(prec) {
403 | case 0:
404 | fw = 0.0;
405 | for (i=jz; i>=0; i--)
406 | fw += fq[i];
407 | y[0] = ih==0 ? fw : -fw;
408 | break;
409 | case 1:
410 | case 2:
411 | fw = 0.0;
412 | for (i=jz; i>=0; i--)
413 | fw += fq[i];
414 | // TODO: drop excess precision here once double_t is used
415 | fw = (double)fw;
416 | y[0] = ih==0 ? fw : -fw;
417 | fw = fq[0]-fw;
418 | for (i=1; i<=jz; i++)
419 | fw += fq[i];
420 | y[1] = ih==0 ? fw : -fw;
421 | break;
422 | case 3: /* painful */
423 | for (i=jz; i>0; i--) {
424 | fw = fq[i-1]+fq[i];
425 | fq[i] += fq[i-1]-fw;
426 | fq[i-1] = fw;
427 | }
428 | for (i=jz; i>1; i--) {
429 | fw = fq[i-1]+fq[i];
430 | fq[i] += fq[i-1]-fw;
431 | fq[i-1] = fw;
432 | }
433 | for (fw=0.0,i=jz; i>=2; i--)
434 | fw += fq[i];
435 | if (ih==0) {
436 | y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
437 | } else {
438 | y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
439 | }
440 | }
441 | return n&7;
442 | }
443 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__sin.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* __sin( x, y, iy)
13 | * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
14 | * Input x is assumed to be bounded by ~pi/4 in magnitude.
15 | * Input y is the tail of x.
16 | * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
17 | *
18 | * Algorithm
19 | * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
20 | * 2. Callers must return sin(-0) = -0 without calling here since our
21 | * odd polynomial is not evaluated in a way that preserves -0.
22 | * Callers may do the optimization sin(x) ~ x for tiny x.
23 | * 3. sin(x) is approximated by a polynomial of degree 13 on
24 | * [0,pi/4]
25 | * 3 13
26 | * sin(x) ~ x + S1*x + ... + S6*x
27 | * where
28 | *
29 | * |sin(x) 2 4 6 8 10 12 | -58
30 | * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
31 | * | x |
32 | *
33 | * 4. sin(x+y) = sin(x) + sin'(x')*y
34 | * ~ sin(x) + (1-x*x/2)*y
35 | * For better accuracy, let
36 | * 3 2 2 2 2
37 | * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
38 | * then 3 2
39 | * sin(x) = x + (S1*x + (x *(r-y/2)+y))
40 | */
41 |
42 | #include "..\libmd.h"
43 |
44 | static const double
45 | S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
46 | S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
47 | S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
48 | S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
49 | S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
50 | S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
51 |
52 | double __sin(double x, double y, int iy)
53 | {
54 | double_t z,r,v,w;
55 |
56 | z = x*x;
57 | w = z*z;
58 | r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6);
59 | v = z*x;
60 | if (iy == 0)
61 | return x + v*(S1 + z*r);
62 | else
63 | return x - ((z*(0.5*y - v*r) - y) - v*S1);
64 | }
65 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/__tan.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */
2 | /*
3 | * ====================================================
4 | * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
5 | *
6 | * Permission to use, copy, modify, and distribute this
7 | * software is freely granted, provided that this notice
8 | * is preserved.
9 | * ====================================================
10 | */
11 | /* __tan( x, y, k )
12 | * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
13 | * Input x is assumed to be bounded by ~pi/4 in magnitude.
14 | * Input y is the tail of x.
15 | * Input odd indicates whether tan (if odd = 0) or -1/tan (if odd = 1) is returned.
16 | *
17 | * Algorithm
18 | * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
19 | * 2. Callers must return tan(-0) = -0 without calling here since our
20 | * odd polynomial is not evaluated in a way that preserves -0.
21 | * Callers may do the optimization tan(x) ~ x for tiny x.
22 | * 3. tan(x) is approximated by a odd polynomial of degree 27 on
23 | * [0,0.67434]
24 | * 3 27
25 | * tan(x) ~ x + T1*x + ... + T13*x
26 | * where
27 | *
28 | * |tan(x) 2 4 26 | -59.2
29 | * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
30 | * | x |
31 | *
32 | * Note: tan(x+y) = tan(x) + tan'(x)*y
33 | * ~ tan(x) + (1+x*x)*y
34 | * Therefore, for better accuracy in computing tan(x+y), let
35 | * 3 2 2 2 2
36 | * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
37 | * then
38 | * 3 2
39 | * tan(x+y) = x + (T1*x + (x *(r+y)+y))
40 | *
41 | * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
42 | * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
43 | * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
44 | */
45 |
46 | #include "..\libmd.h"
47 |
48 | static const double T[] = {
49 | 3.33333333333334091986e-01, /* 3FD55555, 55555563 */
50 | 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */
51 | 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */
52 | 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */
53 | 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */
54 | 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */
55 | 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */
56 | 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */
57 | 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */
58 | 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */
59 | 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */
60 | -1.85586374855275456654e-05, /* BEF375CB, DB605373 */
61 | 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */
62 | },
63 | pio4 = 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */
64 | pio4lo = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */
65 |
66 | double __tan(double x, double y, int odd)
67 | {
68 | double_t z, r, v, w, s, a;
69 | double w0, a0;
70 | uint32_t hx;
71 | int big, sign;
72 |
73 | GET_HIGH_WORD(hx,x);
74 | big = (hx&0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */
75 | if (big) {
76 | sign = hx>>31;
77 | if (sign) {
78 | x = -x;
79 | y = -y;
80 | }
81 | x = (pio4 - x) + (pio4lo - y);
82 | y = 0.0;
83 | }
84 | z = x * x;
85 | w = z * z;
86 | /*
87 | * Break x^5*(T[1]+x^2*T[2]+...) into
88 | * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
89 | * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
90 | */
91 | r = T[1] + w*(T[3] + w*(T[5] + w*(T[7] + w*(T[9] + w*T[11]))));
92 | v = z*(T[2] + w*(T[4] + w*(T[6] + w*(T[8] + w*(T[10] + w*T[12])))));
93 | s = z * x;
94 | r = y + z*(s*(r + v) + y) + s*T[0];
95 | w = x + r;
96 | if (big) {
97 | s = 1 - 2*odd;
98 | v = s - 2.0 * (x + (r - w*w/(w + s)));
99 | return sign ? -v : v;
100 | }
101 | if (!odd)
102 | return w;
103 | /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */
104 | w0 = w;
105 | SET_LOW_WORD(w0, 0);
106 | v = r - (w0 - x); /* w0+v = r+x */
107 | a0 = a = -1.0 / w;
108 | SET_LOW_WORD(a0, 0);
109 | return a0 + a*(1.0 + a0*w0 + a0*v);
110 | }
111 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/_fltused.c:
--------------------------------------------------------------------------------
1 | extern "C" char _fltused = 1;
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/acos.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* acos(x)
13 | * Method :
14 | * acos(x) = pi/2 - asin(x)
15 | * acos(-x) = pi/2 + asin(x)
16 | * For |x|<=0.5
17 | * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
18 | * For x>0.5
19 | * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
20 | * = 2asin(sqrt((1-x)/2))
21 | * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
22 | * = 2f + (2c + 2s*z*R(z))
23 | * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
24 | * for f so that f+c ~ sqrt(z).
25 | * For x<-0.5
26 | * acos(x) = pi - 2asin(sqrt((1-|x|)/2))
27 | * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
28 | *
29 | * Special cases:
30 | * if x is NaN, return x itself;
31 | * if |x|>1, return NaN with invalid signal.
32 | *
33 | * Function needed: sqrt
34 | */
35 |
36 | #include "..\libmd.h"
37 |
38 | static const double
39 | pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
40 | pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
41 | pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
42 | pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
43 | pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
44 | pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
45 | pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
46 | pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
47 | qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
48 | qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
49 | qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
50 | qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
51 |
52 | static double R(double z)
53 | {
54 | double_t p, q;
55 | p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
56 | q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
57 | return p/q;
58 | }
59 |
60 | double acos(double x)
61 | {
62 | double z,w,s,c,df;
63 | uint32_t hx,ix;
64 |
65 | GET_HIGH_WORD(hx, x);
66 | ix = hx & 0x7fffffff;
67 | /* |x| >= 1 or nan */
68 | if (ix >= 0x3ff00000) {
69 | uint32_t lx;
70 |
71 | GET_LOW_WORD(lx,x);
72 | if (((ix-0x3ff00000) | lx) == 0) {
73 | /* acos(1)=0, acos(-1)=pi */
74 | if (hx >> 31)
75 | return 2*pio2_hi + 0x1p-120f;
76 | return 0;
77 | }
78 | return 0/(x-x);
79 | }
80 | /* |x| < 0.5 */
81 | if (ix < 0x3fe00000) {
82 | if (ix <= 0x3c600000) /* |x| < 2**-57 */
83 | return pio2_hi + 0x1p-120f;
84 | return pio2_hi - (x - (pio2_lo-x*R(x*x)));
85 | }
86 | /* x < -0.5 */
87 | if (hx >> 31) {
88 | z = (1.0+x)*0.5;
89 | s = sqrt(z);
90 | w = R(z)*s-pio2_lo;
91 | return 2*(pio2_hi - (s+w));
92 | }
93 | /* x > 0.5 */
94 | z = (1.0-x)*0.5;
95 | s = sqrt(z);
96 | df = s;
97 | SET_LOW_WORD(df,0);
98 | c = (z-df*df)/(s+df);
99 | w = R(z)*s+c;
100 | return 2*(df+w);
101 | }
102 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/acosh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | #if FLT_EVAL_METHOD==2
4 | #undef sqrt
5 | #define sqrt sqrtl
6 | #endif
7 |
8 | /* acosh(x) = log(x + sqrt(x*x-1)) */
9 | double acosh(double x)
10 | {
11 | union {double f; uint64_t i;} u = { x };
12 | unsigned e = u.i >> 52 & 0x7ff;
13 |
14 | /* x < 1 domain error is handled in the called functions */
15 |
16 | if (e < 0x3ff + 1)
17 | /* |x| < 2, up to 2ulp error in [1,1.125] */
18 | return log1p(x-1 + sqrt((x-1)*(x-1)+2*(x-1)));
19 | if (e < 0x3ff + 26)
20 | /* |x| < 0x1p26 */
21 | return log(2*x - 1/(x+sqrt(x*x-1)));
22 | /* |x| >= 0x1p26 or nan */
23 | return log(x) + 0.693147180559945309417232121458176568;
24 | }
25 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/asin.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_asin.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* asin(x)
13 | * Method :
14 | * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
15 | * we approximate asin(x) on [0,0.5] by
16 | * asin(x) = x + x*x^2*R(x^2)
17 | * where
18 | * R(x^2) is a rational approximation of (asin(x)-x)/x^3
19 | * and its remez error is bounded by
20 | * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
21 | *
22 | * For x in [0.5,1]
23 | * asin(x) = pi/2-2*asin(sqrt((1-x)/2))
24 | * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
25 | * then for x>0.98
26 | * asin(x) = pi/2 - 2*(s+s*z*R(z))
27 | * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
28 | * For x<=0.98, let pio4_hi = pio2_hi/2, then
29 | * f = hi part of s;
30 | * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
31 | * and
32 | * asin(x) = pi/2 - 2*(s+s*z*R(z))
33 | * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
34 | * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
35 | *
36 | * Special cases:
37 | * if x is NaN, return x itself;
38 | * if |x|>1, return NaN with invalid signal.
39 | *
40 | */
41 |
42 | #include "..\libmd.h"
43 |
44 | static const double
45 | pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
46 | pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
47 | /* coefficients for R(x^2) */
48 | pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
49 | pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
50 | pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
51 | pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
52 | pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
53 | pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
54 | qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
55 | qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
56 | qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
57 | qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
58 |
59 | static double R(double z)
60 | {
61 | double_t p, q;
62 | p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
63 | q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
64 | return p/q;
65 | }
66 |
67 | double asin(double x)
68 | {
69 | double z,r,s;
70 | uint32_t hx,ix;
71 |
72 | GET_HIGH_WORD(hx, x);
73 | ix = hx & 0x7fffffff;
74 | /* |x| >= 1 or nan */
75 | if (ix >= 0x3ff00000) {
76 | uint32_t lx;
77 | GET_LOW_WORD(lx, x);
78 | if (((ix-0x3ff00000) | lx) == 0)
79 | /* asin(1) = +-pi/2 with inexact */
80 | return x*pio2_hi + 0x1p-120f;
81 | return 0/(x-x);
82 | }
83 | /* |x| < 0.5 */
84 | if (ix < 0x3fe00000) {
85 | /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
86 | if (ix < 0x3e500000 && ix >= 0x00100000)
87 | return x;
88 | return x + x*R(x*x);
89 | }
90 | /* 1 > |x| >= 0.5 */
91 | z = (1 - fabs(x))*0.5;
92 | s = sqrt(z);
93 | r = R(z);
94 | if (ix >= 0x3fef3333) { /* if |x| > 0.975 */
95 | x = pio2_hi-(2*(s+s*r)-pio2_lo);
96 | } else {
97 | double f,c;
98 | /* f+c = sqrt(z) */
99 | f = s;
100 | SET_LOW_WORD(f,0);
101 | c = (z-f*f)/(s+f);
102 | x = 0.5*pio2_hi - (2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f));
103 | }
104 | if (hx >> 31)
105 | return -x;
106 | return x;
107 | }
108 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/asinh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */
4 | double asinh(double x)
5 | {
6 | union {double f; uint64_t i;} u = { x };
7 | unsigned e = u.i >> 52 & 0x7ff;
8 | unsigned s = u.i >> 63;
9 |
10 | /* |x| */
11 | u.i &= (uint64_t)-1/2;
12 | x = u.f;
13 |
14 | if (e >= 0x3ff + 26) {
15 | /* |x| >= 0x1p26 or inf or nan */
16 | x = log(x) + 0.693147180559945309417232121458176568;
17 | } else if (e >= 0x3ff + 1) {
18 | /* |x| >= 2 */
19 | x = log(2*x + 1/(sqrt(x*x+1)+x));
20 | } else if (e >= 0x3ff - 26) {
21 | /* |x| >= 0x1p-26, up to 1.6ulp error in [0.125,0.5] */
22 | x = log1p(x + x*x/(sqrt(x*x+1)+1));
23 | } else {
24 | /* |x| < 0x1p-26, raise inexact if x != 0 */
25 | FORCE_EVAL(x + 0x1p120f);
26 | }
27 | return s ? -x : x;
28 | }
29 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/atan.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* atan(x)
13 | * Method
14 | * 1. Reduce x to positive by atan(x) = -atan(-x).
15 | * 2. According to the integer k=4t+0.25 chopped, t=x, the argument
16 | * is further reduced to one of the following intervals and the
17 | * arctangent of t is evaluated by the corresponding formula:
18 | *
19 | * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
20 | * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
21 | * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
22 | * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
23 | * [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
24 | *
25 | * Constants:
26 | * The hexadecimal values are the intended ones for the following
27 | * constants. The decimal values may be used, provided that the
28 | * compiler will convert from decimal to binary accurately enough
29 | * to produce the hexadecimal values shown.
30 | */
31 |
32 |
33 | #include "..\libmd.h"
34 |
35 | static const double atanhi[] = {
36 | 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
37 | 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
38 | 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
39 | 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
40 | };
41 |
42 | static const double atanlo[] = {
43 | 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
44 | 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
45 | 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
46 | 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
47 | };
48 |
49 | static const double aT[] = {
50 | 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
51 | -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
52 | 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
53 | -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
54 | 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
55 | -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
56 | 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
57 | -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
58 | 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
59 | -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
60 | 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
61 | };
62 |
63 | double atan(double x)
64 | {
65 | double_t w,s1,s2,z;
66 | uint32_t ix,sign;
67 | int id;
68 |
69 | GET_HIGH_WORD(ix, x);
70 | sign = ix >> 31;
71 | ix &= 0x7fffffff;
72 | if (ix >= 0x44100000) { /* if |x| >= 2^66 */
73 | if (isnan(x))
74 | return x;
75 | z = atanhi[3] + 0x1p-120f;
76 | return sign ? -z : z;
77 | }
78 | if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
79 | if (ix < 0x3e400000) { /* |x| < 2^-27 */
80 | if (ix < 0x00100000)
81 | /* raise underflow for subnormal x */
82 | FORCE_EVAL((float)x);
83 | return x;
84 | }
85 | id = -1;
86 | } else {
87 | x = fabs(x);
88 | if (ix < 0x3ff30000) { /* |x| < 1.1875 */
89 | if (ix < 0x3fe60000) { /* 7/16 <= |x| < 11/16 */
90 | id = 0;
91 | x = (2.0*x-1.0)/(2.0+x);
92 | } else { /* 11/16 <= |x| < 19/16 */
93 | id = 1;
94 | x = (x-1.0)/(x+1.0);
95 | }
96 | } else {
97 | if (ix < 0x40038000) { /* |x| < 2.4375 */
98 | id = 2;
99 | x = (x-1.5)/(1.0+1.5*x);
100 | } else { /* 2.4375 <= |x| < 2^66 */
101 | id = 3;
102 | x = -1.0/x;
103 | }
104 | }
105 | }
106 | /* end of argument reduction */
107 | z = x*x;
108 | w = z*z;
109 | /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
110 | s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
111 | s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
112 | if (id < 0)
113 | return x - x*(s1+s2);
114 | z = atanhi[id] - (x*(s1+s2) - atanlo[id] - x);
115 | return sign ? -z : z;
116 | }
117 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/atan2.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_atan2.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | *
12 | */
13 | /* atan2(y,x)
14 | * Method :
15 | * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
16 | * 2. Reduce x to positive by (if x and y are unexceptional):
17 | * ARG (x+iy) = arctan(y/x) ... if x > 0,
18 | * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
19 | *
20 | * Special cases:
21 | *
22 | * ATAN2((anything), NaN ) is NaN;
23 | * ATAN2(NAN , (anything) ) is NaN;
24 | * ATAN2(+-0, +(anything but NaN)) is +-0 ;
25 | * ATAN2(+-0, -(anything but NaN)) is +-pi ;
26 | * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
27 | * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
28 | * ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
29 | * ATAN2(+-INF,+INF ) is +-pi/4 ;
30 | * ATAN2(+-INF,-INF ) is +-3pi/4;
31 | * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
32 | *
33 | * Constants:
34 | * The hexadecimal values are the intended ones for the following
35 | * constants. The decimal values may be used, provided that the
36 | * compiler will convert from decimal to binary accurately enough
37 | * to produce the hexadecimal values shown.
38 | */
39 |
40 | #include "..\libmd.h"
41 |
42 | static const double
43 | pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
44 | pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
45 |
46 | double atan2(double y, double x)
47 | {
48 | double z;
49 | uint32_t m,lx,ly,ix,iy;
50 |
51 | if (isnan(x) || isnan(y))
52 | return x+y;
53 | EXTRACT_WORDS(ix, lx, x);
54 | EXTRACT_WORDS(iy, ly, y);
55 | if (((ix-0x3ff00000) | lx) == 0) /* x = 1.0 */
56 | return atan(y);
57 | m = ((iy>>31)&1) | ((ix>>30)&2); /* 2*sign(x)+sign(y) */
58 | ix = ix & 0x7fffffff;
59 | iy = iy & 0x7fffffff;
60 |
61 | /* when y = 0 */
62 | if ((iy|ly) == 0) {
63 | switch(m) {
64 | case 0:
65 | case 1: return y; /* atan(+-0,+anything)=+-0 */
66 | case 2: return pi; /* atan(+0,-anything) = pi */
67 | case 3: return -pi; /* atan(-0,-anything) =-pi */
68 | }
69 | }
70 | /* when x = 0 */
71 | if ((ix|lx) == 0)
72 | return m&1 ? -pi/2 : pi/2;
73 | /* when x is INF */
74 | if (ix == 0x7ff00000) {
75 | if (iy == 0x7ff00000) {
76 | switch(m) {
77 | case 0: return pi/4; /* atan(+INF,+INF) */
78 | case 1: return -pi/4; /* atan(-INF,+INF) */
79 | case 2: return 3*pi/4; /* atan(+INF,-INF) */
80 | case 3: return -3*pi/4; /* atan(-INF,-INF) */
81 | }
82 | } else {
83 | switch(m) {
84 | case 0: return 0.0; /* atan(+...,+INF) */
85 | case 1: return -0.0; /* atan(-...,+INF) */
86 | case 2: return pi; /* atan(+...,-INF) */
87 | case 3: return -pi; /* atan(-...,-INF) */
88 | }
89 | }
90 | }
91 | /* |y/x| > 0x1p64 */
92 | if (ix+(64<<20) < iy || iy == 0x7ff00000)
93 | return m&1 ? -pi/2 : pi/2;
94 |
95 | /* z = atan(|y/x|) without spurious underflow */
96 | if ((m&2) && iy+(64<<20) < ix) /* |y/x| < 0x1p-64, x<0 */
97 | z = 0;
98 | else
99 | z = atan(fabs(y/x));
100 | switch (m) {
101 | case 0: return z; /* atan(+,+) */
102 | case 1: return -z; /* atan(-,+) */
103 | case 2: return pi - (z-pi_lo); /* atan(+,-) */
104 | default: /* case 3 */
105 | return (z-pi_lo) - pi; /* atan(-,-) */
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/atanh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */
4 | double atanh(double x)
5 | {
6 | union {double f; uint64_t i;} u = { x };
7 | unsigned e = u.i >> 52 & 0x7ff;
8 | unsigned s = u.i >> 63;
9 | double_t y;
10 |
11 | /* |x| */
12 | u.i &= (uint64_t)-1/2;
13 | y = u.f;
14 |
15 | if (e < 0x3ff - 1) {
16 | if (e < 0x3ff - 32) {
17 | /* handle underflow */
18 | if (e == 0)
19 | FORCE_EVAL((float)y);
20 | } else {
21 | /* |x| < 0.5, up to 1.7ulp error */
22 | y = 0.5*log1p(2*y + 2*y*y/(1-y));
23 | }
24 | } else {
25 | /* avoid overflow */
26 | y = 0.5*log1p(2*(y/(1-y)));
27 | }
28 | return s ? -y : y;
29 | }
30 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/ceil.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
4 | #define EPS DBL_EPSILON
5 | #elif FLT_EVAL_METHOD==2
6 | #define EPS LDBL_EPSILON
7 | #endif
8 | static const double_t toint = 1/EPS;
9 |
10 | double ceil(double x)
11 | {
12 | union {double f; uint64_t i;} u = {x};
13 | int e = u.i >> 52 & 0x7ff;
14 | double_t y;
15 |
16 | if (e >= 0x3ff+52 || x == 0)
17 | return x;
18 | /* y = int(x) - x, where int(x) is an integer neighbor of x */
19 | if (u.i >> 63)
20 | y = x - toint + toint - x;
21 | else
22 | y = x + toint - toint - x;
23 | /* special case because of non-nearest rounding modes */
24 | if (e <= 0x3ff-1) {
25 | FORCE_EVAL(y);
26 | return u.i >> 63 ? -0.0 : 1;
27 | }
28 | if (y < 0)
29 | return x + y + 1;
30 | return x + y;
31 | }
32 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/copysign.c:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the MicroPython project, http://micropython.org/
3 | *
4 | * The MIT License (MIT)
5 | *
6 | * Copyright (c) 2013, 2014 Damien P. George
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy
9 | * of this software and associated documentation files (the "Software"), to deal
10 | * in the Software without restriction, including without limitation the rights
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | * copies of the Software, and to permit persons to whom the Software is
13 | * furnished to do so, subject to the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be included in
16 | * all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | * THE SOFTWARE.
25 | */
26 |
27 | #include "..\libmd.h"
28 |
29 | typedef union {
30 | double d;
31 | struct {
32 | uint64_t m : 52;
33 | uint64_t e : 11;
34 | uint64_t s : 1;
35 | };
36 | } double_s_t;
37 |
38 | double copysign(double x, double y) {
39 | double_s_t dx = { x };
40 | double_s_t dy = { y };
41 |
42 | // copy sign bit;
43 | dx.s = dy.s;
44 |
45 | return dx.d;
46 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/cos.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* cos(x)
13 | * Return cosine function of x.
14 | *
15 | * kernel function:
16 | * __sin ... sine function on [-pi/4,pi/4]
17 | * __cos ... cosine function on [-pi/4,pi/4]
18 | * __rem_pio2 ... argument reduction routine
19 | *
20 | * Method.
21 | * Let S,C and T denote the sin, cos and tan respectively on
22 | * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
23 | * in [-pi/4 , +pi/4], and let n = k mod 4.
24 | * We have
25 | *
26 | * n sin(x) cos(x) tan(x)
27 | * ----------------------------------------------------------
28 | * 0 S C T
29 | * 1 C -S -1/T
30 | * 2 -S -C T
31 | * 3 -C S -1/T
32 | * ----------------------------------------------------------
33 | *
34 | * Special cases:
35 | * Let trig be any of sin, cos, or tan.
36 | * trig(+-INF) is NaN, with signals;
37 | * trig(NaN) is that NaN;
38 | *
39 | * Accuracy:
40 | * TRIG(x) returns trig(x) nearly rounded
41 | */
42 |
43 | #include "..\libmd.h"
44 |
45 | double cos(double x)
46 | {
47 | double y[2];
48 | uint32_t ix;
49 | unsigned n;
50 |
51 | GET_HIGH_WORD(ix, x);
52 | ix &= 0x7fffffff;
53 |
54 | /* |x| ~< pi/4 */
55 | if (ix <= 0x3fe921fb) {
56 | if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */
57 | /* raise inexact if x!=0 */
58 | FORCE_EVAL(x + 0x1p120f);
59 | return 1.0;
60 | }
61 | return __cos(x, 0);
62 | }
63 |
64 | /* cos(Inf or NaN) is NaN */
65 | if (ix >= 0x7ff00000)
66 | return x-x;
67 |
68 | /* argument reduction */
69 | n = __rem_pio2(x, y);
70 | switch (n&3) {
71 | case 0: return __cos(y[0], y[1]);
72 | case 1: return -__sin(y[0], y[1], 1);
73 | case 2: return -__cos(y[0], y[1]);
74 | default:
75 | return __sin(y[0], y[1], 1);
76 | }
77 | }
78 |
79 | float cosf(float f)
80 | {
81 | return cos(f);
82 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/cosh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* cosh(x) = (exp(x) + 1/exp(x))/2
4 | * = 1 + 0.5*(exp(x)-1)*(exp(x)-1)/exp(x)
5 | * = 1 + x*x/2 + o(x^4)
6 | */
7 | double cosh(double x)
8 | {
9 | union {double f; uint64_t i;} u = { x };
10 | uint32_t w;
11 | double t;
12 |
13 | /* |x| */
14 | u.i &= (uint64_t)-1/2;
15 | x = u.f;
16 | w = u.i >> 32;
17 |
18 | /* |x| < log(2) */
19 | if (w < 0x3fe62e42) {
20 | if (w < 0x3ff00000 - (26<<20)) {
21 | /* raise inexact if x!=0 */
22 | FORCE_EVAL(x + 0x1p120f);
23 | return 1;
24 | }
25 | t = expm1(x);
26 | return 1 + t*t/(2*(1+t));
27 | }
28 |
29 | /* |x| < log(DBL_MAX) */
30 | if (w < 0x40862e42) {
31 | t = exp(x);
32 | /* note: if x>log(0x1p26) then the 1/t is not needed */
33 | return 0.5*(t + 1/t);
34 | }
35 |
36 | /* |x| > log(DBL_MAX) or nan */
37 | /* note: the result is stored to handle overflow */
38 | t = __expo2(x);
39 | return t;
40 | }
41 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/erf.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_erf.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* double erf(double x)
13 | * double erfc(double x)
14 | * x
15 | * 2 |\
16 | * erf(x) = --------- | exp(-t*t)dt
17 | * sqrt(pi) \|
18 | * 0
19 | *
20 | * erfc(x) = 1-erf(x)
21 | * Note that
22 | * erf(-x) = -erf(x)
23 | * erfc(-x) = 2 - erfc(x)
24 | *
25 | * Method:
26 | * 1. For |x| in [0, 0.84375]
27 | * erf(x) = x + x*R(x^2)
28 | * erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
29 | * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
30 | * where R = P/Q where P is an odd poly of degree 8 and
31 | * Q is an odd poly of degree 10.
32 | * -57.90
33 | * | R - (erf(x)-x)/x | <= 2
34 | *
35 | *
36 | * Remark. The formula is derived by noting
37 | * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
38 | * and that
39 | * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
40 | * is close to one. The interval is chosen because the fix
41 | * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
42 | * near 0.6174), and by some experiment, 0.84375 is chosen to
43 | * guarantee the error is less than one ulp for erf.
44 | *
45 | * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
46 | * c = 0.84506291151 rounded to single (24 bits)
47 | * erf(x) = sign(x) * (c + P1(s)/Q1(s))
48 | * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
49 | * 1+(c+P1(s)/Q1(s)) if x < 0
50 | * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
51 | * Remark: here we use the taylor series expansion at x=1.
52 | * erf(1+s) = erf(1) + s*Poly(s)
53 | * = 0.845.. + P1(s)/Q1(s)
54 | * That is, we use rational approximation to approximate
55 | * erf(1+s) - (c = (single)0.84506291151)
56 | * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
57 | * where
58 | * P1(s) = degree 6 poly in s
59 | * Q1(s) = degree 6 poly in s
60 | *
61 | * 3. For x in [1.25,1/0.35(~2.857143)],
62 | * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
63 | * erf(x) = 1 - erfc(x)
64 | * where
65 | * R1(z) = degree 7 poly in z, (z=1/x^2)
66 | * S1(z) = degree 8 poly in z
67 | *
68 | * 4. For x in [1/0.35,28]
69 | * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
70 | * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28
96 | * erf(x) = sign(x) *(1 - tiny) (raise inexact)
97 | * erfc(x) = tiny*tiny (raise underflow) if x > 0
98 | * = 2 - tiny if x<0
99 | *
100 | * 7. Special case:
101 | * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
102 | * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
103 | * erfc/erf(NaN) is NaN
104 | */
105 |
106 | #include "..\libmd.h"
107 |
108 | static const double
109 | erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
110 | /*
111 | * Coefficients for approximation to erf on [0,0.84375]
112 | */
113 | efx8 = 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
114 | pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
115 | pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
116 | pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
117 | pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
118 | pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
119 | qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
120 | qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
121 | qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
122 | qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
123 | qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
124 | /*
125 | * Coefficients for approximation to erf in [0.84375,1.25]
126 | */
127 | pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
128 | pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
129 | pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
130 | pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
131 | pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
132 | pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
133 | pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
134 | qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
135 | qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
136 | qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
137 | qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
138 | qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
139 | qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
140 | /*
141 | * Coefficients for approximation to erfc in [1.25,1/0.35]
142 | */
143 | ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
144 | ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
145 | ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
146 | ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
147 | ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
148 | ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
149 | ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
150 | ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
151 | sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
152 | sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
153 | sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
154 | sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
155 | sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
156 | sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
157 | sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
158 | sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
159 | /*
160 | * Coefficients for approximation to erfc in [1/.35,28]
161 | */
162 | rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
163 | rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
164 | rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
165 | rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
166 | rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
167 | rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
168 | rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
169 | sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
170 | sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
171 | sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
172 | sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
173 | sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
174 | sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
175 | sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
176 |
177 | static double erfc1(double x)
178 | {
179 | double_t s,P,Q;
180 |
181 | s = fabs(x) - 1;
182 | P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
183 | Q = 1+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
184 | return 1 - erx - P/Q;
185 | }
186 |
187 | static double erfc2(uint32_t ix, double x)
188 | {
189 | double_t s,R,S;
190 | double z;
191 |
192 | if (ix < 0x3ff40000) /* |x| < 1.25 */
193 | return erfc1(x);
194 |
195 | x = fabs(x);
196 | s = 1/(x*x);
197 | if (ix < 0x4006db6d) { /* |x| < 1/.35 ~ 2.85714 */
198 | R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
199 | ra5+s*(ra6+s*ra7))))));
200 | S = 1.0+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
201 | sa5+s*(sa6+s*(sa7+s*sa8)))))));
202 | } else { /* |x| > 1/.35 */
203 | R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
204 | rb5+s*rb6)))));
205 | S = 1.0+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
206 | sb5+s*(sb6+s*sb7))))));
207 | }
208 | z = x;
209 | SET_LOW_WORD(z,0);
210 | return exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S)/x;
211 | }
212 |
213 | double erf(double x)
214 | {
215 | double r,s,z,y;
216 | uint32_t ix;
217 | int sign;
218 |
219 | GET_HIGH_WORD(ix, x);
220 | sign = ix>>31;
221 | ix &= 0x7fffffff;
222 | if (ix >= 0x7ff00000) {
223 | /* erf(nan)=nan, erf(+-inf)=+-1 */
224 | return 1-2*sign + 1/x;
225 | }
226 | if (ix < 0x3feb0000) { /* |x| < 0.84375 */
227 | if (ix < 0x3e300000) { /* |x| < 2**-28 */
228 | /* avoid underflow */
229 | return 0.125*(8*x + efx8*x);
230 | }
231 | z = x*x;
232 | r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
233 | s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
234 | y = r/s;
235 | return x + x*y;
236 | }
237 | if (ix < 0x40180000) /* 0.84375 <= |x| < 6 */
238 | y = 1 - erfc2(ix,x);
239 | else
240 | y = 1 - 0x1p-1022;
241 | return sign ? -y : y;
242 | }
243 |
244 | double erfc(double x)
245 | {
246 | double r,s,z,y;
247 | uint32_t ix;
248 | int sign;
249 |
250 | GET_HIGH_WORD(ix, x);
251 | sign = ix>>31;
252 | ix &= 0x7fffffff;
253 | if (ix >= 0x7ff00000) {
254 | /* erfc(nan)=nan, erfc(+-inf)=0,2 */
255 | return 2*sign + 1/x;
256 | }
257 | if (ix < 0x3feb0000) { /* |x| < 0.84375 */
258 | if (ix < 0x3c700000) /* |x| < 2**-56 */
259 | return 1.0 - x;
260 | z = x*x;
261 | r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
262 | s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
263 | y = r/s;
264 | if (sign || ix < 0x3fd00000) { /* x < 1/4 */
265 | return 1.0 - (x+x*y);
266 | }
267 | return 0.5 - (x - 0.5 + x*y);
268 | }
269 | if (ix < 0x403c0000) { /* 0.84375 <= |x| < 28 */
270 | return sign ? 2 - erfc2(ix,x) : erfc2(ix,x);
271 | }
272 | return sign ? 2 - 0x1p-1022 : 0x1p-1022*0x1p-1022;
273 | }
274 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/exp.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Permission to use, copy, modify, and distribute this
7 | * software is freely granted, provided that this notice
8 | * is preserved.
9 | * ====================================================
10 | */
11 | /* exp(x)
12 | * Returns the exponential of x.
13 | *
14 | * Method
15 | * 1. Argument reduction:
16 | * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
17 | * Given x, find r and integer k such that
18 | *
19 | * x = k*ln2 + r, |r| <= 0.5*ln2.
20 | *
21 | * Here r will be represented as r = hi-lo for better
22 | * accuracy.
23 | *
24 | * 2. Approximation of exp(r) by a special rational function on
25 | * the interval [0,0.34658]:
26 | * Write
27 | * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
28 | * We use a special Remez algorithm on [0,0.34658] to generate
29 | * a polynomial of degree 5 to approximate R. The maximum error
30 | * of this polynomial approximation is bounded by 2**-59. In
31 | * other words,
32 | * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
33 | * (where z=r*r, and the values of P1 to P5 are listed below)
34 | * and
35 | * | 5 | -59
36 | * | 2.0+P1*z+...+P5*z - R(z) | <= 2
37 | * | |
38 | * The computation of exp(r) thus becomes
39 | * 2*r
40 | * exp(r) = 1 + ----------
41 | * R(r) - r
42 | * r*c(r)
43 | * = 1 + r + ----------- (for better accuracy)
44 | * 2 - c(r)
45 | * where
46 | * 2 4 10
47 | * c(r) = r - (P1*r + P2*r + ... + P5*r ).
48 | *
49 | * 3. Scale back to obtain exp(x):
50 | * From step 1, we have
51 | * exp(x) = 2^k * exp(r)
52 | *
53 | * Special cases:
54 | * exp(INF) is INF, exp(NaN) is NaN;
55 | * exp(-INF) is 0, and
56 | * for finite argument, only exp(0)=1 is exact.
57 | *
58 | * Accuracy:
59 | * according to an error analysis, the error is always less than
60 | * 1 ulp (unit in the last place).
61 | *
62 | * Misc. info.
63 | * For IEEE double
64 | * if x > 709.782712893383973096 then exp(x) overflows
65 | * if x < -745.133219101941108420 then exp(x) underflows
66 | */
67 |
68 | #include "..\libmd.h"
69 |
70 | static const double
71 | half[2] = {0.5,-0.5},
72 | ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
73 | ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
74 | invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
75 | P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
76 | P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
77 | P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
78 | P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
79 | P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
80 |
81 | double exp(double x)
82 | {
83 | double_t hi, lo, c, xx, y;
84 | int k, sign;
85 | uint32_t hx;
86 |
87 | GET_HIGH_WORD(hx, x);
88 | sign = hx>>31;
89 | hx &= 0x7fffffff; /* high word of |x| */
90 |
91 | /* special cases */
92 | if (hx >= 0x4086232b) { /* if |x| >= 708.39... */
93 | if (isnan(x))
94 | return x;
95 | if (x > 709.782712893383973096) {
96 | /* overflow if x!=inf */
97 | x *= 0x1p1023;
98 | return x;
99 | }
100 | if (x < -708.39641853226410622) {
101 | /* underflow if x!=-inf */
102 | FORCE_EVAL((float)(-0x1p-149/x));
103 | if (x < -745.13321910194110842)
104 | return 0;
105 | }
106 | }
107 |
108 | /* argument reduction */
109 | if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
110 | if (hx >= 0x3ff0a2b2) /* if |x| >= 1.5 ln2 */
111 | k = (int)(invln2*x + half[sign]);
112 | else
113 | k = 1 - sign - sign;
114 | hi = x - k*ln2hi; /* k*ln2hi is exact here */
115 | lo = k*ln2lo;
116 | x = hi - lo;
117 | } else if (hx > 0x3e300000) { /* if |x| > 2**-28 */
118 | k = 0;
119 | hi = x;
120 | lo = 0;
121 | } else {
122 | /* inexact if x!=0 */
123 | FORCE_EVAL(0x1p1023 + x);
124 | return 1 + x;
125 | }
126 |
127 | /* x is now in primary range */
128 | xx = x*x;
129 | c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5))));
130 | y = 1 + (x*c/(2-c) - lo + hi);
131 | if (k == 0)
132 | return y;
133 | return scalbn(y, k);
134 | }
135 |
136 | float expf(float f)
137 | {
138 | return exp(f);
139 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/expm1.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_expm1.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* expm1(x)
13 | * Returns exp(x)-1, the exponential of x minus 1.
14 | *
15 | * Method
16 | * 1. Argument reduction:
17 | * Given x, find r and integer k such that
18 | *
19 | * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
20 | *
21 | * Here a correction term c will be computed to compensate
22 | * the error in r when rounded to a floating-point number.
23 | *
24 | * 2. Approximating expm1(r) by a special rational function on
25 | * the interval [0,0.34658]:
26 | * Since
27 | * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
28 | * we define R1(r*r) by
29 | * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
30 | * That is,
31 | * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
32 | * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
33 | * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
34 | * We use a special Remez algorithm on [0,0.347] to generate
35 | * a polynomial of degree 5 in r*r to approximate R1. The
36 | * maximum error of this polynomial approximation is bounded
37 | * by 2**-61. In other words,
38 | * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
39 | * where Q1 = -1.6666666666666567384E-2,
40 | * Q2 = 3.9682539681370365873E-4,
41 | * Q3 = -9.9206344733435987357E-6,
42 | * Q4 = 2.5051361420808517002E-7,
43 | * Q5 = -6.2843505682382617102E-9;
44 | * z = r*r,
45 | * with error bounded by
46 | * | 5 | -61
47 | * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
48 | * | |
49 | *
50 | * expm1(r) = exp(r)-1 is then computed by the following
51 | * specific way which minimize the accumulation rounding error:
52 | * 2 3
53 | * r r [ 3 - (R1 + R1*r/2) ]
54 | * expm1(r) = r + --- + --- * [--------------------]
55 | * 2 2 [ 6 - r*(3 - R1*r/2) ]
56 | *
57 | * To compensate the error in the argument reduction, we use
58 | * expm1(r+c) = expm1(r) + c + expm1(r)*c
59 | * ~ expm1(r) + c + r*c
60 | * Thus c+r*c will be added in as the correction terms for
61 | * expm1(r+c). Now rearrange the term to avoid optimization
62 | * screw up:
63 | * ( 2 2 )
64 | * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
65 | * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
66 | * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
67 | * ( )
68 | *
69 | * = r - E
70 | * 3. Scale back to obtain expm1(x):
71 | * From step 1, we have
72 | * expm1(x) = either 2^k*[expm1(r)+1] - 1
73 | * = or 2^k*[expm1(r) + (1-2^-k)]
74 | * 4. Implementation notes:
75 | * (A). To save one multiplication, we scale the coefficient Qi
76 | * to Qi*2^i, and replace z by (x^2)/2.
77 | * (B). To achieve maximum accuracy, we compute expm1(x) by
78 | * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
79 | * (ii) if k=0, return r-E
80 | * (iii) if k=-1, return 0.5*(r-E)-0.5
81 | * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
82 | * else return 1.0+2.0*(r-E);
83 | * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
84 | * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
85 | * (vii) return 2^k(1-((E+2^-k)-r))
86 | *
87 | * Special cases:
88 | * expm1(INF) is INF, expm1(NaN) is NaN;
89 | * expm1(-INF) is -1, and
90 | * for finite argument, only expm1(0)=0 is exact.
91 | *
92 | * Accuracy:
93 | * according to an error analysis, the error is always less than
94 | * 1 ulp (unit in the last place).
95 | *
96 | * Misc. info.
97 | * For IEEE double
98 | * if x > 7.09782712893383973096e+02 then expm1(x) overflow
99 | *
100 | * Constants:
101 | * The hexadecimal values are the intended ones for the following
102 | * constants. The decimal values may be used, provided that the
103 | * compiler will convert from decimal to binary accurately enough
104 | * to produce the hexadecimal values shown.
105 | */
106 |
107 | #include "..\libmd.h"
108 |
109 | static const double
110 | o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
111 | ln2_hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
112 | ln2_lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
113 | invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
114 | /* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */
115 | Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */
116 | Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
117 | Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
118 | Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
119 | Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
120 |
121 | double expm1(double x)
122 | {
123 | double_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk;
124 | union {double f; uint64_t i;} u = {x};
125 | uint32_t hx = u.i>>32 & 0x7fffffff;
126 | int k, sign = u.i>>63;
127 |
128 | /* filter out huge and non-finite argument */
129 | if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */
130 | if (isnan(x))
131 | return x;
132 | if (sign)
133 | return -1;
134 | if (x > o_threshold) {
135 | x *= 0x1p1023;
136 | return x;
137 | }
138 | }
139 |
140 | /* argument reduction */
141 | if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
142 | if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
143 | if (!sign) {
144 | hi = x - ln2_hi;
145 | lo = ln2_lo;
146 | k = 1;
147 | } else {
148 | hi = x + ln2_hi;
149 | lo = -ln2_lo;
150 | k = -1;
151 | }
152 | } else {
153 | k = invln2*x + (sign ? -0.5 : 0.5);
154 | t = k;
155 | hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
156 | lo = t*ln2_lo;
157 | }
158 | x = hi-lo;
159 | c = (hi-x)-lo;
160 | } else if (hx < 0x3c900000) { /* |x| < 2**-54, return x */
161 | if (hx < 0x00100000)
162 | FORCE_EVAL((float)x);
163 | return x;
164 | } else
165 | k = 0;
166 |
167 | /* x is now in primary range */
168 | hfx = 0.5*x;
169 | hxs = x*hfx;
170 | r1 = 1.0+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
171 | t = 3.0-r1*hfx;
172 | e = hxs*((r1-t)/(6.0 - x*t));
173 | if (k == 0) /* c is 0 */
174 | return x - (x*e-hxs);
175 | e = x*(e-c) - c;
176 | e -= hxs;
177 | /* exp(x) ~ 2^k (x_reduced - e + 1) */
178 | if (k == -1)
179 | return 0.5*(x-e) - 0.5;
180 | if (k == 1) {
181 | if (x < -0.25)
182 | return -2.0*(e-(x+0.5));
183 | return 1.0+2.0*(x-e);
184 | }
185 | u.i = (uint64_t)(0x3ff + k)<<52; /* 2^k */
186 | twopk = u.f;
187 | if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */
188 | y = x - e + 1.0;
189 | if (k == 1024)
190 | y = y*2.0*0x1p1023;
191 | else
192 | y = y*twopk;
193 | return y - 1.0;
194 | }
195 | u.i = (uint64_t)(0x3ff - k)<<52; /* 2^-k */
196 | if (k < 20)
197 | y = (x-e+(1-u.f))*twopk;
198 | else
199 | y = (x-(e+u.f)+1)*twopk;
200 | return y;
201 | }
202 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/fabs.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | typedef union
4 | {
5 | double d;
6 | struct
7 | {
8 | uint64_t m : 52;
9 | uint64_t e : 11;
10 | uint64_t s : 1;
11 | };
12 | } double_s_t;
13 |
14 | double fabs( double x )
15 | {
16 | double_s_t dx = { x };
17 | dx.s = 0;
18 | return dx.d;
19 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/floor.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
4 | #define EPS DBL_EPSILON
5 | #elif FLT_EVAL_METHOD==2
6 | #define EPS LDBL_EPSILON
7 | #endif
8 | static const double_t toint = 1/EPS;
9 |
10 | double floor(double x)
11 | {
12 | union {double f; uint64_t i;} u = {x};
13 | int e = u.i >> 52 & 0x7ff;
14 | double_t y;
15 |
16 | if (e >= 0x3ff+52 || x == 0)
17 | return x;
18 | /* y = int(x) - x, where int(x) is an integer neighbor of x */
19 | if (u.i >> 63)
20 | y = x - toint + toint - x;
21 | else
22 | y = x + toint - toint - x;
23 | /* special case because of non-nearest rounding modes */
24 | if (e <= 0x3ff-1) {
25 | FORCE_EVAL(y);
26 | return u.i >> 63 ? -1 : 0;
27 | }
28 | if (y > 0)
29 | return x + y - 1;
30 | return x + y;
31 | }
32 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/fmod.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double fmod(double x, double y)
4 | {
5 | union {double f; uint64_t i;} ux = {x}, uy = {y};
6 | int ex = ux.i>>52 & 0x7ff;
7 | int ey = uy.i>>52 & 0x7ff;
8 | int sx = ux.i>>63;
9 | uint64_t i;
10 |
11 | /* in the followings uxi should be ux.i, but then gcc wrongly adds */
12 | /* float load/store to inner loops ruining performance and code size */
13 | uint64_t uxi = ux.i;
14 |
15 | if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff)
16 | return (x*y)/(x*y);
17 | if (uxi<<1 <= uy.i<<1) {
18 | if (uxi<<1 == uy.i<<1)
19 | return 0*x;
20 | return x;
21 | }
22 |
23 | /* normalize x and y */
24 | if (!ex) {
25 | for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1);
26 | uxi <<= -ex + 1;
27 | } else {
28 | uxi &= -1ULL >> 12;
29 | uxi |= 1ULL << 52;
30 | }
31 | if (!ey) {
32 | for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1);
33 | uy.i <<= -ey + 1;
34 | } else {
35 | uy.i &= -1ULL >> 12;
36 | uy.i |= 1ULL << 52;
37 | }
38 |
39 | /* x mod y */
40 | for (; ex > ey; ex--) {
41 | i = uxi - uy.i;
42 | if (i >> 63 == 0) {
43 | if (i == 0)
44 | return 0*x;
45 | uxi = i;
46 | }
47 | uxi <<= 1;
48 | }
49 | i = uxi - uy.i;
50 | if (i >> 63 == 0) {
51 | if (i == 0)
52 | return 0*x;
53 | uxi = i;
54 | }
55 | for (; uxi>>52 == 0; uxi <<= 1, ex--);
56 |
57 | /* scale result */
58 | if (ex > 0) {
59 | uxi -= 1ULL << 52;
60 | uxi |= (uint64_t)ex << 52;
61 | } else {
62 | uxi >>= -ex + 1;
63 | }
64 | uxi |= (uint64_t)sx << 63;
65 | ux.i = uxi;
66 | return ux.f;
67 | }
68 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/fpclassify.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | int fpclassify(double x)
4 | {
5 | union {double f; uint64_t i;} u = {x};
6 | int e = u.i>>52 & 0x7ff;
7 | if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO;
8 | if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE;
9 | return FP_NORMAL;
10 | }
11 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/frexp.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double frexp(double x, int *e)
4 | {
5 | union { double d; uint64_t i; } y = { x };
6 | int ee = y.i>>52 & 0x7ff;
7 |
8 | if (!ee) {
9 | if (x) {
10 | x = frexp(x*0x1p64, e);
11 | *e -= 64;
12 | } else *e = 0;
13 | return x;
14 | } else if (ee == 0x7ff) {
15 | return x;
16 | }
17 |
18 | *e = ee - 0x3fe;
19 | y.i &= 0x800fffffffffffffull;
20 | y.i |= 0x3fe0000000000000ull;
21 | return y.d;
22 | }
23 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/ldexp.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double ldexp(double x, int n)
4 | {
5 | return scalbn(x, n);
6 | }
7 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/lgamma.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double __lgamma_r(double, int*);
4 |
5 | double lgamma(double x) {
6 | int sign;
7 | return __lgamma_r(x, &sign);
8 | }
9 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/log.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_log.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* log(x)
13 | * Return the logarithm of x
14 | *
15 | * Method :
16 | * 1. Argument Reduction: find k and f such that
17 | * x = 2^k * (1+f),
18 | * where sqrt(2)/2 < 1+f < sqrt(2) .
19 | *
20 | * 2. Approximation of log(1+f).
21 | * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
22 | * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
23 | * = 2s + s*R
24 | * We use a special Remez algorithm on [0,0.1716] to generate
25 | * a polynomial of degree 14 to approximate R The maximum error
26 | * of this polynomial approximation is bounded by 2**-58.45. In
27 | * other words,
28 | * 2 4 6 8 10 12 14
29 | * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
30 | * (the values of Lg1 to Lg7 are listed in the program)
31 | * and
32 | * | 2 14 | -58.45
33 | * | Lg1*s +...+Lg7*s - R(z) | <= 2
34 | * | |
35 | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
36 | * In order to guarantee error in log below 1ulp, we compute log
37 | * by
38 | * log(1+f) = f - s*(f - R) (if f is not too large)
39 | * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
40 | *
41 | * 3. Finally, log(x) = k*ln2 + log(1+f).
42 | * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
43 | * Here ln2 is split into two floating point number:
44 | * ln2_hi + ln2_lo,
45 | * where n*ln2_hi is always exact for |n| < 2000.
46 | *
47 | * Special cases:
48 | * log(x) is NaN with signal if x < 0 (including -INF) ;
49 | * log(+INF) is +INF; log(0) is -INF with signal;
50 | * log(NaN) is that NaN with no signal.
51 | *
52 | * Accuracy:
53 | * according to an error analysis, the error is always less than
54 | * 1 ulp (unit in the last place).
55 | *
56 | * Constants:
57 | * The hexadecimal values are the intended ones for the following
58 | * constants. The decimal values may be used, provided that the
59 | * compiler will convert from decimal to binary accurately enough
60 | * to produce the hexadecimal values shown.
61 | */
62 |
63 | #include "..\libmd.h"
64 |
65 | static const double
66 | ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
67 | ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
68 | Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
69 | Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
70 | Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
71 | Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
72 | Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
73 | Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
74 | Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
75 |
76 | double log(double x)
77 | {
78 | union {double f; uint64_t i;} u = {x};
79 | double_t hfsq,f,s,z,R,w,t1,t2,dk;
80 | uint32_t hx;
81 | int k;
82 |
83 | hx = u.i>>32;
84 | k = 0;
85 | if (hx < 0x00100000 || hx>>31) {
86 | if (u.i<<1 == 0)
87 | return -1/(x*x); /* log(+-0)=-inf */
88 | if (hx>>31)
89 | return (x-x)/0.0; /* log(-#) = NaN */
90 | /* subnormal number, scale x up */
91 | k -= 54;
92 | x *= 0x1p54;
93 | u.f = x;
94 | hx = u.i>>32;
95 | } else if (hx >= 0x7ff00000) {
96 | return x;
97 | } else if (hx == 0x3ff00000 && u.i<<32 == 0)
98 | return 0;
99 |
100 | /* reduce x into [sqrt(2)/2, sqrt(2)] */
101 | hx += 0x3ff00000 - 0x3fe6a09e;
102 | k += (int)(hx>>20) - 0x3ff;
103 | hx = (hx&0x000fffff) + 0x3fe6a09e;
104 | u.i = (uint64_t)hx<<32 | (u.i&0xffffffff);
105 | x = u.f;
106 |
107 | f = x - 1.0;
108 | hfsq = 0.5*f*f;
109 | s = f/(2.0+f);
110 | z = s*s;
111 | w = z*z;
112 | t1 = w*(Lg2+w*(Lg4+w*Lg6));
113 | t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
114 | R = t2 + t1;
115 | dk = k;
116 | return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi;
117 | }
118 |
119 | float logf(float f)
120 | {
121 | return log(f);
122 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/log10.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | static const double _M_LN10 = 2.302585092994046;
4 |
5 | double log10(double x) {
6 | return log(x) / (double)_M_LN10;
7 | }
8 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/log1p.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* double log1p(double x)
13 | * Return the natural logarithm of 1+x.
14 | *
15 | * Method :
16 | * 1. Argument Reduction: find k and f such that
17 | * 1+x = 2^k * (1+f),
18 | * where sqrt(2)/2 < 1+f < sqrt(2) .
19 | *
20 | * Note. If k=0, then f=x is exact. However, if k!=0, then f
21 | * may not be representable exactly. In that case, a correction
22 | * term is need. Let u=1+x rounded. Let c = (1+x)-u, then
23 | * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
24 | * and add back the correction term c/u.
25 | * (Note: when x > 2**53, one can simply return log(x))
26 | *
27 | * 2. Approximation of log(1+f): See log.c
28 | *
29 | * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c
30 | *
31 | * Special cases:
32 | * log1p(x) is NaN with signal if x < -1 (including -INF) ;
33 | * log1p(+INF) is +INF; log1p(-1) is -INF with signal;
34 | * log1p(NaN) is that NaN with no signal.
35 | *
36 | * Accuracy:
37 | * according to an error analysis, the error is always less than
38 | * 1 ulp (unit in the last place).
39 | *
40 | * Constants:
41 | * The hexadecimal values are the intended ones for the following
42 | * constants. The decimal values may be used, provided that the
43 | * compiler will convert from decimal to binary accurately enough
44 | * to produce the hexadecimal values shown.
45 | *
46 | * Note: Assuming log() return accurate answer, the following
47 | * algorithm can be used to compute log1p(x) to within a few ULP:
48 | *
49 | * u = 1+x;
50 | * if(u==1.0) return x ; else
51 | * return log(u)*(x/(u-1.0));
52 | *
53 | * See HP-15C Advanced Functions Handbook, p.193.
54 | */
55 |
56 | #include "..\libmd.h"
57 |
58 | static const double
59 | ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
60 | ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
61 | Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
62 | Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
63 | Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
64 | Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
65 | Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
66 | Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
67 | Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
68 |
69 | double log1p(double x)
70 | {
71 | union {double f; uint64_t i;} u = {x};
72 | double_t hfsq,f,c,s,z,R,w,t1,t2,dk;
73 | uint32_t hx,hu;
74 | int k;
75 |
76 | hx = u.i>>32;
77 | k = 1;
78 | if (hx < 0x3fda827a || hx>>31) { /* 1+x < sqrt(2)+ */
79 | if (hx >= 0xbff00000) { /* x <= -1.0 */
80 | if (x == -1)
81 | return x/0.0; /* log1p(-1) = -inf */
82 | return (x-x)/0.0; /* log1p(x<-1) = NaN */
83 | }
84 | if (hx<<1 < 0x3ca00000<<1) { /* |x| < 2**-53 */
85 | /* underflow if subnormal */
86 | if ((hx&0x7ff00000) == 0)
87 | FORCE_EVAL((float)x);
88 | return x;
89 | }
90 | if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
91 | k = 0;
92 | c = 0;
93 | f = x;
94 | }
95 | } else if (hx >= 0x7ff00000)
96 | return x;
97 | if (k) {
98 | u.f = 1 + x;
99 | hu = u.i>>32;
100 | hu += 0x3ff00000 - 0x3fe6a09e;
101 | k = (int)(hu>>20) - 0x3ff;
102 | /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
103 | if (k < 54) {
104 | c = k >= 2 ? 1-(u.f-x) : x-(u.f-1);
105 | c /= u.f;
106 | } else
107 | c = 0;
108 | /* reduce u into [sqrt(2)/2, sqrt(2)] */
109 | hu = (hu&0x000fffff) + 0x3fe6a09e;
110 | u.i = (uint64_t)hu<<32 | (u.i&0xffffffff);
111 | f = u.f - 1;
112 | }
113 | hfsq = 0.5*f*f;
114 | s = f/(2.0+f);
115 | z = s*s;
116 | w = z*z;
117 | t1 = w*(Lg2+w*(Lg4+w*Lg6));
118 | t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
119 | R = t2 + t1;
120 | dk = k;
121 | return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi;
122 | }
123 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/modf.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double modf(double x, double *iptr)
4 | {
5 | union {double f; uint64_t i;} u = {x};
6 | uint64_t mask;
7 | int e = (int)(u.i>>52 & 0x7ff) - 0x3ff;
8 |
9 | /* no fractional part */
10 | if (e >= 52) {
11 | *iptr = x;
12 | if (e == 0x400 && u.i<<12 != 0) /* nan */
13 | return x;
14 | u.i &= 1ULL<<63;
15 | return u.f;
16 | }
17 |
18 | /* no integral part*/
19 | if (e < 0) {
20 | u.i &= 1ULL<<63;
21 | *iptr = u.f;
22 | return x;
23 | }
24 |
25 | mask = -1ULL>>12>>e;
26 | if ((u.i & mask) == 0) {
27 | *iptr = x;
28 | u.i &= 1ULL<<63;
29 | return u.f;
30 | }
31 | u.i &= ~mask;
32 | *iptr = u.f;
33 | return x - u.f;
34 | }
35 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/nearbyint.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* nearbyint is the same as rint, but it must not raise the inexact exception */
4 |
5 | double nearbyint(double x)
6 | {
7 | #ifdef FE_INEXACT
8 | #pragma STDC FENV_ACCESS ON
9 | int e;
10 |
11 | e = fetestexcept(FE_INEXACT);
12 | #endif
13 | x = rint(x);
14 | #ifdef FE_INEXACT
15 | if (!e)
16 | feclearexcept(FE_INEXACT);
17 | #endif
18 | return x;
19 | }
20 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/pow.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Permission to use, copy, modify, and distribute this
7 | * software is freely granted, provided that this notice
8 | * is preserved.
9 | * ====================================================
10 | */
11 | /* pow(x,y) return x**y
12 | *
13 | * n
14 | * Method: Let x = 2 * (1+f)
15 | * 1. Compute and return log2(x) in two pieces:
16 | * log2(x) = w1 + w2,
17 | * where w1 has 53-24 = 29 bit trailing zeros.
18 | * 2. Perform y*log2(x) = n+y' by simulating muti-precision
19 | * arithmetic, where |y'|<=0.5.
20 | * 3. Return x**y = 2**n*exp(y'*log2)
21 | *
22 | * Special cases:
23 | * 1. (anything) ** 0 is 1
24 | * 2. 1 ** (anything) is 1
25 | * 3. (anything except 1) ** NAN is NAN
26 | * 4. NAN ** (anything except 0) is NAN
27 | * 5. +-(|x| > 1) ** +INF is +INF
28 | * 6. +-(|x| > 1) ** -INF is +0
29 | * 7. +-(|x| < 1) ** +INF is +0
30 | * 8. +-(|x| < 1) ** -INF is +INF
31 | * 9. -1 ** +-INF is 1
32 | * 10. +0 ** (+anything except 0, NAN) is +0
33 | * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
34 | * 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyzero
35 | * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyzero
36 | * 14. -0 ** (+odd integer) is -0
37 | * 15. -0 ** (-odd integer) is -INF, raise divbyzero
38 | * 16. +INF ** (+anything except 0,NAN) is +INF
39 | * 17. +INF ** (-anything except 0,NAN) is +0
40 | * 18. -INF ** (+odd integer) is -INF
41 | * 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer)
42 | * 20. (anything) ** 1 is (anything)
43 | * 21. (anything) ** -1 is 1/(anything)
44 | * 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
45 | * 23. (-anything except 0 and inf) ** (non-integer) is NAN
46 | *
47 | * Accuracy:
48 | * pow(x,y) returns x**y nearly rounded. In particular
49 | * pow(integer,integer)
50 | * always returns the correct integer provided it is
51 | * representable.
52 | *
53 | * Constants :
54 | * The hexadecimal values are the intended ones for the following
55 | * constants. The decimal values may be used, provided that the
56 | * compiler will convert from decimal to binary accurately enough
57 | * to produce the hexadecimal values shown.
58 | */
59 |
60 | #include "..\libmd.h"
61 |
62 | static const double
63 | bp[] = {1.0, 1.5,},
64 | dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
65 | dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
66 | two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
67 | huge = 1.0e300,
68 | tiny = 1.0e-300,
69 | /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
70 | L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
71 | L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
72 | L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
73 | L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
74 | L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
75 | L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
76 | P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
77 | P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
78 | P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
79 | P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
80 | P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
81 | lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
82 | lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
83 | lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
84 | ovt = 8.0085662595372944372e-017, /* -(1024-log2(ovfl+.5ulp)) */
85 | cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
86 | cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
87 | cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
88 | ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
89 | ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
90 | ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
91 |
92 | double pow(double x, double y)
93 | {
94 | double z,ax,z_h,z_l,p_h,p_l;
95 | double y1,t1,t2,r,s,t,u,v,w;
96 | int32_t i,j,k,yisint,n;
97 | int32_t hx,hy,ix,iy;
98 | uint32_t lx,ly;
99 |
100 | EXTRACT_WORDS(hx, lx, x);
101 | EXTRACT_WORDS(hy, ly, y);
102 | ix = hx & 0x7fffffff;
103 | iy = hy & 0x7fffffff;
104 |
105 | /* x**0 = 1, even if x is NaN */
106 | if ((iy|ly) == 0)
107 | return 1.0;
108 | /* 1**y = 1, even if y is NaN */
109 | if (hx == 0x3ff00000 && lx == 0)
110 | return 1.0;
111 | /* NaN if either arg is NaN */
112 | if (ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) ||
113 | iy > 0x7ff00000 || (iy == 0x7ff00000 && ly != 0))
114 | return x + y;
115 |
116 | /* determine if y is an odd int when x < 0
117 | * yisint = 0 ... y is not an integer
118 | * yisint = 1 ... y is an odd int
119 | * yisint = 2 ... y is an even int
120 | */
121 | yisint = 0;
122 | if (hx < 0) {
123 | if (iy >= 0x43400000)
124 | yisint = 2; /* even integer y */
125 | else if (iy >= 0x3ff00000) {
126 | k = (iy>>20) - 0x3ff; /* exponent */
127 | if (k > 20) {
128 | uint32_t j = ly>>(52-k);
129 | if ((j<<(52-k)) == ly)
130 | yisint = 2 - (j&1);
131 | } else if (ly == 0) {
132 | uint32_t j = iy>>(20-k);
133 | if ((j<<(20-k)) == iy)
134 | yisint = 2 - (j&1);
135 | }
136 | }
137 | }
138 |
139 | /* special value of y */
140 | if (ly == 0) {
141 | if (iy == 0x7ff00000) { /* y is +-inf */
142 | if (((ix-0x3ff00000)|lx) == 0) /* (-1)**+-inf is 1 */
143 | return 1.0;
144 | else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */
145 | return hy >= 0 ? y : 0.0;
146 | else /* (|x|<1)**+-inf = 0,inf */
147 | return hy >= 0 ? 0.0 : -y;
148 | }
149 | if (iy == 0x3ff00000) { /* y is +-1 */
150 | if (hy >= 0)
151 | return x;
152 | y = 1/x;
153 | #if FLT_EVAL_METHOD!=0
154 | {
155 | union {double f; uint64_t i;} u = {y};
156 | uint64_t i = u.i & -1ULL/2;
157 | if (i>>52 == 0 && (i&(i-1)))
158 | FORCE_EVAL((float)y);
159 | }
160 | #endif
161 | return y;
162 | }
163 | if (hy == 0x40000000) /* y is 2 */
164 | return x*x;
165 | if (hy == 0x3fe00000) { /* y is 0.5 */
166 | if (hx >= 0) /* x >= +0 */
167 | return sqrt(x);
168 | }
169 | }
170 |
171 | ax = fabs(x);
172 | /* special value of x */
173 | if (lx == 0) {
174 | if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { /* x is +-0,+-inf,+-1 */
175 | z = ax;
176 | if (hy < 0) /* z = (1/|x|) */
177 | z = 1.0/z;
178 | if (hx < 0) {
179 | if (((ix-0x3ff00000)|yisint) == 0) {
180 | z = (z-z)/(z-z); /* (-1)**non-int is NaN */
181 | } else if (yisint == 1)
182 | z = -z; /* (x<0)**odd = -(|x|**odd) */
183 | }
184 | return z;
185 | }
186 | }
187 |
188 | s = 1.0; /* sign of result */
189 | if (hx < 0) {
190 | if (yisint == 0) /* (x<0)**(non-int) is NaN */
191 | return (x-x)/(x-x);
192 | if (yisint == 1) /* (x<0)**(odd int) */
193 | s = -1.0;
194 | }
195 |
196 | /* |y| is huge */
197 | if (iy > 0x41e00000) { /* if |y| > 2**31 */
198 | if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */
199 | if (ix <= 0x3fefffff)
200 | return hy < 0 ? huge*huge : tiny*tiny;
201 | if (ix >= 0x3ff00000)
202 | return hy > 0 ? huge*huge : tiny*tiny;
203 | }
204 | /* over/underflow if x is not close to one */
205 | if (ix < 0x3fefffff)
206 | return hy < 0 ? s*huge*huge : s*tiny*tiny;
207 | if (ix > 0x3ff00000)
208 | return hy > 0 ? s*huge*huge : s*tiny*tiny;
209 | /* now |1-x| is tiny <= 2**-20, suffice to compute
210 | log(x) by x-x^2/2+x^3/3-x^4/4 */
211 | t = ax - 1.0; /* t has 20 trailing zeros */
212 | w = (t*t)*(0.5 - t*(0.3333333333333333333333-t*0.25));
213 | u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
214 | v = t*ivln2_l - w*ivln2;
215 | t1 = u + v;
216 | SET_LOW_WORD(t1, 0);
217 | t2 = v - (t1-u);
218 | } else {
219 | double ss,s2,s_h,s_l,t_h,t_l;
220 | n = 0;
221 | /* take care subnormal number */
222 | if (ix < 0x00100000) {
223 | ax *= two53;
224 | n -= 53;
225 | GET_HIGH_WORD(ix,ax);
226 | }
227 | n += ((ix)>>20) - 0x3ff;
228 | j = ix & 0x000fffff;
229 | /* determine interval */
230 | ix = j | 0x3ff00000; /* normalize ix */
231 | if (j <= 0x3988E) /* |x|>1)|0x20000000) + 0x00080000 + (k<<18));
251 | t_l = ax - (t_h-bp[k]);
252 | s_l = v*((u-s_h*t_h)-s_h*t_l);
253 | /* compute log(ax) */
254 | s2 = ss*ss;
255 | r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
256 | r += s_l*(s_h+ss);
257 | s2 = s_h*s_h;
258 | t_h = 3.0 + s2 + r;
259 | SET_LOW_WORD(t_h, 0);
260 | t_l = r - ((t_h-3.0)-s2);
261 | /* u+v = ss*(1+...) */
262 | u = s_h*t_h;
263 | v = s_l*t_h + t_l*ss;
264 | /* 2/(3log2)*(ss+...) */
265 | p_h = u + v;
266 | SET_LOW_WORD(p_h, 0);
267 | p_l = v - (p_h-u);
268 | z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
269 | z_l = cp_l*p_h+p_l*cp + dp_l[k];
270 | /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
271 | t = (double)n;
272 | t1 = ((z_h + z_l) + dp_h[k]) + t;
273 | SET_LOW_WORD(t1, 0);
274 | t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
275 | }
276 |
277 | /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
278 | y1 = y;
279 | SET_LOW_WORD(y1, 0);
280 | p_l = (y-y1)*t1 + y*t2;
281 | p_h = y1*t1;
282 | z = p_l + p_h;
283 | EXTRACT_WORDS(j, i, z);
284 | if (j >= 0x40900000) { /* z >= 1024 */
285 | if (((j-0x40900000)|i) != 0) /* if z > 1024 */
286 | return s*huge*huge; /* overflow */
287 | if (p_l + ovt > z - p_h)
288 | return s*huge*huge; /* overflow */
289 | } else if ((j&0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ // FIXME: instead of abs(j) use unsigned j
290 | if (((j-0xc090cc00)|i) != 0) /* z < -1075 */
291 | return s*tiny*tiny; /* underflow */
292 | if (p_l <= z - p_h)
293 | return s*tiny*tiny; /* underflow */
294 | }
295 | /*
296 | * compute 2**(p_h+p_l)
297 | */
298 | i = j & 0x7fffffff;
299 | k = (i>>20) - 0x3ff;
300 | n = 0;
301 | if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
302 | n = j + (0x00100000>>(k+1));
303 | k = ((n&0x7fffffff)>>20) - 0x3ff; /* new k for n */
304 | t = 0.0;
305 | SET_HIGH_WORD(t, n & ~(0x000fffff>>k));
306 | n = ((n&0x000fffff)|0x00100000)>>(20-k);
307 | if (j < 0)
308 | n = -n;
309 | p_h -= t;
310 | }
311 | t = p_l + p_h;
312 | SET_LOW_WORD(t, 0);
313 | u = t*lg2_h;
314 | v = (p_l-(t-p_h))*lg2 + t*lg2_l;
315 | z = u + v;
316 | w = v - (z-u);
317 | t = z*z;
318 | t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
319 | r = (z*t1)/(t1-2.0) - (w + z*w);
320 | z = 1.0 - (r-z);
321 | GET_HIGH_WORD(j, z);
322 | j += n<<20;
323 | if ((j>>20) <= 0) /* subnormal output */
324 | z = scalbn(z,n);
325 | else
326 | SET_HIGH_WORD(z, j);
327 | return s*z;
328 | }
329 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/rint.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "..\libmd.h"
3 |
4 | #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
5 | #define EPS DBL_EPSILON
6 | #elif FLT_EVAL_METHOD==2
7 | #define EPS LDBL_EPSILON
8 | #endif
9 | static const double_t toint = 1/EPS;
10 |
11 | double rint(double x)
12 | {
13 | union {double f; uint64_t i;} u = {x};
14 | int e = u.i>>52 & 0x7ff;
15 | int s = u.i>>63;
16 | double_t y;
17 |
18 | if (e >= 0x3ff+52)
19 | return x;
20 | if (s)
21 | y = x - toint + toint;
22 | else
23 | y = x + toint - toint;
24 | if (y == 0)
25 | return s ? -0.0 : 0;
26 | return y;
27 | }
28 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/scalbn.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double scalbn(double x, int n)
4 | {
5 | union {double f; uint64_t i;} u;
6 | double_t y = x;
7 |
8 | if (n > 1023) {
9 | y *= 0x1p1023;
10 | n -= 1023;
11 | if (n > 1023) {
12 | y *= 0x1p1023;
13 | n -= 1023;
14 | if (n > 1023)
15 | n = 1023;
16 | }
17 | } else if (n < -1022) {
18 | /* make sure final n < -53 to avoid double
19 | rounding in the subnormal range */
20 | y *= 0x1p-1022 * 0x1p53;
21 | n += 1022 - 53;
22 | if (n < -1022) {
23 | y *= 0x1p-1022 * 0x1p53;
24 | n += 1022 - 53;
25 | if (n < -1022)
26 | n = -1022;
27 | }
28 | }
29 | u.i = (uint64_t)(0x3ff+n)<<52;
30 | x = y * u.f;
31 | return x;
32 | }
33 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/signbit.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | int signbit(double x)
4 | {
5 | union {
6 | double d;
7 | uint64_t i;
8 | } y = { x };
9 | return y.i>>63;
10 | }
11 |
12 |
13 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/sin.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* sin(x)
13 | * Return sine function of x.
14 | *
15 | * kernel function:
16 | * __sin ... sine function on [-pi/4,pi/4]
17 | * __cos ... cose function on [-pi/4,pi/4]
18 | * __rem_pio2 ... argument reduction routine
19 | *
20 | * Method.
21 | * Let S,C and T denote the sin, cos and tan respectively on
22 | * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
23 | * in [-pi/4 , +pi/4], and let n = k mod 4.
24 | * We have
25 | *
26 | * n sin(x) cos(x) tan(x)
27 | * ----------------------------------------------------------
28 | * 0 S C T
29 | * 1 C -S -1/T
30 | * 2 -S -C T
31 | * 3 -C S -1/T
32 | * ----------------------------------------------------------
33 | *
34 | * Special cases:
35 | * Let trig be any of sin, cos, or tan.
36 | * trig(+-INF) is NaN, with signals;
37 | * trig(NaN) is that NaN;
38 | *
39 | * Accuracy:
40 | * TRIG(x) returns trig(x) nearly rounded
41 | */
42 |
43 | #include "..\libmd.h"
44 |
45 | double sin(double x)
46 | {
47 | double y[2];
48 | uint32_t ix;
49 | unsigned n;
50 |
51 | /* High word of x. */
52 | GET_HIGH_WORD(ix, x);
53 | ix &= 0x7fffffff;
54 |
55 | /* |x| ~< pi/4 */
56 | if (ix <= 0x3fe921fb) {
57 | if (ix < 0x3e500000) { /* |x| < 2**-26 */
58 | /* raise inexact if x != 0 and underflow if subnormal*/
59 | FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
60 | return x;
61 | }
62 | return __sin(x, 0.0, 0);
63 | }
64 |
65 | /* sin(Inf or NaN) is NaN */
66 | if (ix >= 0x7ff00000)
67 | return x - x;
68 |
69 | /* argument reduction needed */
70 | n = __rem_pio2(x, y);
71 | switch (n&3) {
72 | case 0: return __sin(y[0], y[1], 1);
73 | case 1: return __cos(y[0], y[1]);
74 | case 2: return -__sin(y[0], y[1], 1);
75 | default:
76 | return -__cos(y[0], y[1]);
77 | }
78 | }
79 |
80 | float sinf(float f)
81 | {
82 | return sin(f);
83 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/sinh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | /* sinh(x) = (exp(x) - 1/exp(x))/2
4 | * = (exp(x)-1 + (exp(x)-1)/exp(x))/2
5 | * = x + x^3/6 + o(x^5)
6 | */
7 | double sinh(double x)
8 | {
9 | union {double f; uint64_t i;} u = { x };
10 | uint32_t w;
11 | double t, h, absx;
12 |
13 | h = 0.5;
14 | if (u.i >> 63)
15 | h = -h;
16 | /* |x| */
17 | u.i &= (uint64_t)-1/2;
18 | absx = u.f;
19 | w = u.i >> 32;
20 |
21 | /* |x| < log(DBL_MAX) */
22 | if (w < 0x40862e42) {
23 | t = expm1(absx);
24 | if (w < 0x3ff00000) {
25 | if (w < 0x3ff00000 - (26<<20))
26 | /* note: inexact and underflow are raised by expm1 */
27 | /* note: this branch avoids spurious underflow */
28 | return x;
29 | return h*(2*t - t*t/(t+1));
30 | }
31 | /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */
32 | return h*(t + t/(t+1));
33 | }
34 |
35 | /* |x| > log(DBL_MAX) or nan */
36 | /* note: the result is stored to handle overflow */
37 | t = 2*h*__expo2(absx);
38 | return t;
39 | }
40 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/sqrt.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* sqrt(x)
13 | * Return correctly rounded sqrt.
14 | * ------------------------------------------
15 | * | Use the hardware sqrt if you have one |
16 | * ------------------------------------------
17 | * Method:
18 | * Bit by bit method using integer arithmetic. (Slow, but portable)
19 | * 1. Normalization
20 | * Scale x to y in [1,4) with even powers of 2:
21 | * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
22 | * sqrt(x) = 2^k * sqrt(y)
23 | * 2. Bit by bit computation
24 | * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
25 | * i 0
26 | * i+1 2
27 | * s = 2*q , and y = 2 * ( y - q ). (1)
28 | * i i i i
29 | *
30 | * To compute q from q , one checks whether
31 | * i+1 i
32 | *
33 | * -(i+1) 2
34 | * (q + 2 ) <= y. (2)
35 | * i
36 | * -(i+1)
37 | * If (2) is false, then q = q ; otherwise q = q + 2 .
38 | * i+1 i i+1 i
39 | *
40 | * With some algebric manipulation, it is not difficult to see
41 | * that (2) is equivalent to
42 | * -(i+1)
43 | * s + 2 <= y (3)
44 | * i i
45 | *
46 | * The advantage of (3) is that s and y can be computed by
47 | * i i
48 | * the following recurrence formula:
49 | * if (3) is false
50 | *
51 | * s = s , y = y ; (4)
52 | * i+1 i i+1 i
53 | *
54 | * otherwise,
55 | * -i -(i+1)
56 | * s = s + 2 , y = y - s - 2 (5)
57 | * i+1 i i+1 i i
58 | *
59 | * One may easily use induction to prove (4) and (5).
60 | * Note. Since the left hand side of (3) contain only i+2 bits,
61 | * it does not necessary to do a full (53-bit) comparison
62 | * in (3).
63 | * 3. Final rounding
64 | * After generating the 53 bits result, we compute one more bit.
65 | * Together with the remainder, we can decide whether the
66 | * result is exact, bigger than 1/2ulp, or less than 1/2ulp
67 | * (it will never equal to 1/2ulp).
68 | * The rounding mode can be detected by checking whether
69 | * huge + tiny is equal to huge, and whether huge - tiny is
70 | * equal to huge for some floating point number "huge" and "tiny".
71 | *
72 | * Special cases:
73 | * sqrt(+-0) = +-0 ... exact
74 | * sqrt(inf) = inf
75 | * sqrt(-ve) = NaN ... with invalid signal
76 | * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
77 | */
78 |
79 | #include "..\libmd.h"
80 |
81 | static const double tiny = 1.0e-300;
82 |
83 | double sqrt(double x)
84 | {
85 | double z;
86 | int32_t sign = (int)0x80000000;
87 | int32_t ix0,s0,q,m,t,i;
88 | uint32_t r,t1,s1,ix1,q1;
89 |
90 | EXTRACT_WORDS(ix0, ix1, x);
91 |
92 | /* take care of Inf and NaN */
93 | if ((ix0&0x7ff00000) == 0x7ff00000) {
94 | return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
95 | }
96 | /* take care of zero */
97 | if (ix0 <= 0) {
98 | if (((ix0&~sign)|ix1) == 0)
99 | return x; /* sqrt(+-0) = +-0 */
100 | if (ix0 < 0)
101 | return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
102 | }
103 | /* normalize x */
104 | m = ix0>>20;
105 | if (m == 0) { /* subnormal x */
106 | while (ix0 == 0) {
107 | m -= 21;
108 | ix0 |= (ix1>>11);
109 | ix1 <<= 21;
110 | }
111 | for (i=0; (ix0&0x00100000) == 0; i++)
112 | ix0<<=1;
113 | m -= i - 1;
114 | ix0 |= ix1>>(32-i);
115 | ix1 <<= i;
116 | }
117 | m -= 1023; /* unbias exponent */
118 | ix0 = (ix0&0x000fffff)|0x00100000;
119 | if (m & 1) { /* odd m, double x to make it even */
120 | ix0 += ix0 + ((ix1&sign)>>31);
121 | ix1 += ix1;
122 | }
123 | m >>= 1; /* m = [m/2] */
124 |
125 | /* generate sqrt(x) bit by bit */
126 | ix0 += ix0 + ((ix1&sign)>>31);
127 | ix1 += ix1;
128 | q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
129 | r = 0x00200000; /* r = moving bit from right to left */
130 |
131 | while (r != 0) {
132 | t = s0 + r;
133 | if (t <= ix0) {
134 | s0 = t + r;
135 | ix0 -= t;
136 | q += r;
137 | }
138 | ix0 += ix0 + ((ix1&sign)>>31);
139 | ix1 += ix1;
140 | r >>= 1;
141 | }
142 |
143 | r = sign;
144 | while (r != 0) {
145 | t1 = s1 + r;
146 | t = s0;
147 | if (t < ix0 || (t == ix0 && t1 <= ix1)) {
148 | s1 = t1 + r;
149 | if ((t1&sign) == sign && (s1&sign) == 0)
150 | s0++;
151 | ix0 -= t;
152 | if (ix1 < t1)
153 | ix0--;
154 | ix1 -= t1;
155 | q1 += r;
156 | }
157 | ix0 += ix0 + ((ix1&sign)>>31);
158 | ix1 += ix1;
159 | r >>= 1;
160 | }
161 |
162 | /* use floating add to find out rounding direction */
163 | if ((ix0|ix1) != 0) {
164 | z = 1.0 - tiny; /* raise inexact flag */
165 | if (z >= 1.0) {
166 | z = 1.0 + tiny;
167 | if (q1 == (uint32_t)0xffffffff) {
168 | q1 = 0;
169 | q++;
170 | } else if (z > 1.0) {
171 | if (q1 == (uint32_t)0xfffffffe)
172 | q++;
173 | q1 += 2;
174 | } else
175 | q1 += q1 & 1;
176 | }
177 | }
178 | ix0 = (q>>1) + 0x3fe00000;
179 | ix1 = q1>>1;
180 | if (q&1)
181 | ix1 |= sign;
182 | ix0 += m << 20;
183 | INSERT_WORDS(z, ix0, ix1);
184 | return z;
185 | }
186 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/tan.c:
--------------------------------------------------------------------------------
1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */
2 | /*
3 | * ====================================================
4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 | *
6 | * Developed at SunPro, a Sun Microsystems, Inc. business.
7 | * Permission to use, copy, modify, and distribute this
8 | * software is freely granted, provided that this notice
9 | * is preserved.
10 | * ====================================================
11 | */
12 | /* tan(x)
13 | * Return tangent function of x.
14 | *
15 | * kernel function:
16 | * __tan ... tangent function on [-pi/4,pi/4]
17 | * __rem_pio2 ... argument reduction routine
18 | *
19 | * Method.
20 | * Let S,C and T denote the sin, cos and tan respectively on
21 | * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
22 | * in [-pi/4 , +pi/4], and let n = k mod 4.
23 | * We have
24 | *
25 | * n sin(x) cos(x) tan(x)
26 | * ----------------------------------------------------------
27 | * 0 S C T
28 | * 1 C -S -1/T
29 | * 2 -S -C T
30 | * 3 -C S -1/T
31 | * ----------------------------------------------------------
32 | *
33 | * Special cases:
34 | * Let trig be any of sin, cos, or tan.
35 | * trig(+-INF) is NaN, with signals;
36 | * trig(NaN) is that NaN;
37 | *
38 | * Accuracy:
39 | * TRIG(x) returns trig(x) nearly rounded
40 | */
41 |
42 | #include "..\libmd.h"
43 |
44 | double tan(double x)
45 | {
46 | double y[2];
47 | uint32_t ix;
48 | unsigned n;
49 |
50 | GET_HIGH_WORD(ix, x);
51 | ix &= 0x7fffffff;
52 |
53 | /* |x| ~< pi/4 */
54 | if (ix <= 0x3fe921fb) {
55 | if (ix < 0x3e400000) { /* |x| < 2**-27 */
56 | /* raise inexact if x!=0 and underflow if subnormal */
57 | FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
58 | return x;
59 | }
60 | return __tan(x, 0.0, 0);
61 | }
62 |
63 | /* tan(Inf or NaN) is NaN */
64 | if (ix >= 0x7ff00000)
65 | return x - x;
66 |
67 | /* argument reduction */
68 | n = __rem_pio2(x, y);
69 | return __tan(y[0], y[1], n&1);
70 | }
71 |
72 | float tanf(float f)
73 | {
74 | return tan(f);
75 | }
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/tanh.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double tanh(double x) {
4 | int sign = 0;
5 | if (x < 0) {
6 | sign = 1;
7 | x = -x;
8 | }
9 | x = expm1(-2 * x);
10 | x = x / (x + 2);
11 | return sign ? x : -x;
12 | }
13 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/tgamma.c:
--------------------------------------------------------------------------------
1 | /*
2 | "A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964)
3 | "Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001)
4 | "An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004)
5 |
6 | approximation method:
7 |
8 | (x - 0.5) S(x)
9 | Gamma(x) = (x + g - 0.5) * ----------------
10 | exp(x + g - 0.5)
11 |
12 | with
13 | a1 a2 a3 aN
14 | S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ]
15 | x + 1 x + 2 x + 3 x + N
16 |
17 | with a0, a1, a2, a3,.. aN constants which depend on g.
18 |
19 | for x < 0 the following reflection formula is used:
20 |
21 | Gamma(x)*Gamma(-x) = -pi/(x sin(pi x))
22 |
23 | most ideas and constants are from boost and python
24 | */
25 | #include "..\libmd.h"
26 |
27 | static const double pi = 3.141592653589793238462643383279502884;
28 |
29 | /* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */
30 | static double sinpi(double x)
31 | {
32 | int n;
33 |
34 | /* argument reduction: x = |x| mod 2 */
35 | /* spurious inexact when x is odd int */
36 | x = x * 0.5;
37 | x = 2 * (x - floor(x));
38 |
39 | /* reduce x into [-.25,.25] */
40 | n = 4 * x;
41 | n = (n+1)/2;
42 | x -= n * 0.5;
43 |
44 | x *= pi;
45 | switch (n) {
46 | default: /* case 4 */
47 | case 0:
48 | return __sin(x, 0, 0);
49 | case 1:
50 | return __cos(x, 0);
51 | case 2:
52 | return __sin(-x, 0, 0);
53 | case 3:
54 | return -__cos(x, 0);
55 | }
56 | }
57 |
58 | #define N 12
59 | //static const double g = 6.024680040776729583740234375;
60 | static const double gmhalf = 5.524680040776729583740234375;
61 | static const double Snum[N+1] = {
62 | 23531376880.410759688572007674451636754734846804940,
63 | 42919803642.649098768957899047001988850926355848959,
64 | 35711959237.355668049440185451547166705960488635843,
65 | 17921034426.037209699919755754458931112671403265390,
66 | 6039542586.3520280050642916443072979210699388420708,
67 | 1439720407.3117216736632230727949123939715485786772,
68 | 248874557.86205415651146038641322942321632125127801,
69 | 31426415.585400194380614231628318205362874684987640,
70 | 2876370.6289353724412254090516208496135991145378768,
71 | 186056.26539522349504029498971604569928220784236328,
72 | 8071.6720023658162106380029022722506138218516325024,
73 | 210.82427775157934587250973392071336271166969580291,
74 | 2.5066282746310002701649081771338373386264310793408,
75 | };
76 | static const double Sden[N+1] = {
77 | 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535,
78 | 2637558, 357423, 32670, 1925, 66, 1,
79 | };
80 | /* n! for small integer n */
81 | static const double fact[] = {
82 | 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0,
83 | 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0,
84 | 355687428096000.0, 6402373705728000.0, 121645100408832000.0,
85 | 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
86 | };
87 |
88 | /* S(x) rational function for positive x */
89 | static double S(double x)
90 | {
91 | double_t num = 0, den = 0;
92 | int i;
93 |
94 | /* to avoid overflow handle large x differently */
95 | if (x < 8)
96 | for (i = N; i >= 0; i--) {
97 | num = num * x + Snum[i];
98 | den = den * x + Sden[i];
99 | }
100 | else
101 | for (i = 0; i <= N; i++) {
102 | num = num / x + Snum[i];
103 | den = den / x + Sden[i];
104 | }
105 | return num/den;
106 | }
107 |
108 | double tgamma(double x)
109 | {
110 | union {double f; uint64_t i;} u = {x};
111 | double absx, y;
112 | double_t dy, z, r;
113 | uint32_t ix = u.i>>32 & 0x7fffffff;
114 | int sign = u.i>>63;
115 |
116 | /* special cases */
117 | if (ix >= 0x7ff00000)
118 | /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
119 | return x + INFINITY;
120 | if (ix < (0x3ff-54)<<20)
121 | /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
122 | return 1/x;
123 |
124 | /* integer arguments */
125 | /* raise inexact when non-integer */
126 | if (x == floor(x)) {
127 | if (sign)
128 | return NAN;
129 | if (x <= sizeof fact/sizeof *fact)
130 | return fact[(int)x - 1];
131 | }
132 |
133 | /* x >= 172: tgamma(x)=inf with overflow */
134 | /* x =< -184: tgamma(x)=+-0 with underflow */
135 | if (ix >= 0x40670000) { /* |x| >= 184 */
136 | if (sign) {
137 | FORCE_EVAL((float)(0x1p-126/x));
138 | if (floor(x) * 0.5 == floor(x * 0.5))
139 | return 0;
140 | return -0.0;
141 | }
142 | x *= 0x1p1023;
143 | return x;
144 | }
145 |
146 | absx = sign ? -x : x;
147 |
148 | /* handle the error of x + g - 0.5 */
149 | y = absx + gmhalf;
150 | if (absx > gmhalf) {
151 | dy = y - absx;
152 | dy -= gmhalf;
153 | } else {
154 | dy = y - gmhalf;
155 | dy -= absx;
156 | }
157 |
158 | z = absx - 0.5;
159 | r = S(absx) * exp(-y);
160 | if (x < 0) {
161 | /* reflection formula for negative x */
162 | /* sinpi(absx) is not 0, integers are already handled */
163 | r = -pi / (sinpi(absx) * absx * r);
164 | dy = -dy;
165 | z = -z;
166 | }
167 | r += dy * (gmhalf+0.5) * r / y;
168 | z = pow(y, 0.5*z);
169 | y = r * z * z;
170 | return y;
171 | }
172 |
173 | #if 1
174 | double __lgamma_r(double x, int *sign)
175 | {
176 | double r, absx;
177 |
178 | *sign = 1;
179 |
180 | /* special cases */
181 | if (!isfinite(x))
182 | /* lgamma(nan)=nan, lgamma(+-inf)=inf */
183 | return x*x;
184 |
185 | /* integer arguments */
186 | if (x == floor(x) && x <= 2) {
187 | /* n <= 0: lgamma(n)=inf with divbyzero */
188 | /* n == 1,2: lgamma(n)=0 */
189 | if (x <= 0)
190 | return INFINITY;
191 | return 0;
192 | }
193 |
194 | absx = fabs(x);
195 |
196 | /* lgamma(x) ~ -log(|x|) for tiny |x| */
197 | if (absx < 0x1p-54) {
198 | *sign = 1 - 2*!!signbit(x);
199 | return -log(absx);
200 | }
201 |
202 | /* use tgamma for smaller |x| */
203 | if (absx < 128) {
204 | x = tgamma(x);
205 | *sign = 1 - 2*!!signbit(x);
206 | return log(fabs(x));
207 | }
208 |
209 | /* second term (log(S)-g) could be more precise here.. */
210 | /* or with stirling: (|x|-0.5)*(log(|x|)-1) + poly(1/|x|) */
211 | r = (absx-0.5)*(log(absx+gmhalf)-1) + (log(S(absx)) - (gmhalf+0.5));
212 | if (x < 0) {
213 | /* reflection formula for negative x */
214 | x = sinpi(absx);
215 | *sign = 2*!!signbit(x) - 1;
216 | r = log(pi/(fabs(x)*absx)) - r;
217 | }
218 | return r;
219 | }
220 |
221 | //weak_alias(__lgamma_r, lgamma_r);
222 | #endif
223 |
--------------------------------------------------------------------------------
/NtLisp/crt/libmd/trunc.c:
--------------------------------------------------------------------------------
1 | #include "..\libmd.h"
2 |
3 | double trunc(double x)
4 | {
5 | union {double f; uint64_t i;} u = {x};
6 | int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12;
7 | uint64_t m;
8 |
9 | if (e >= 52 + 12)
10 | return x;
11 | if (e < 12)
12 | e = 1;
13 | m = -1ULL >> e;
14 | if ((u.i & m) == 0)
15 | return x;
16 | FORCE_EVAL(x + 0x1p120f);
17 | u.i &= ~m;
18 | return u.f;
19 | }
20 |
--------------------------------------------------------------------------------
/NtLisp/crt/memory.cpp:
--------------------------------------------------------------------------------
1 | #include "crt.h"
2 |
3 | __declspec( restrict ) void* malloc( size_t n )
4 | {
5 | return ExAllocatePoolWithTag( NonPagedPool, n, 'NLUA' );
6 | }
7 |
8 | void free( void* p )
9 | {
10 | if ( p ) ExFreePoolWithTag( p, 'NLUA' );
11 | }
12 |
13 | void* __cdecl operator new( size_t n )
14 | {
15 | return malloc( n );
16 | }
17 |
18 | void* operator new[ ] ( size_t n )
19 | {
20 | return malloc( n );
21 | }
22 |
23 | void __cdecl operator delete[ ] ( void* p )
24 | {
25 | return free( p );
26 | }
27 |
28 | void __cdecl operator delete( void* p, size_t n )
29 | {
30 | return free( p );
31 | }
32 |
33 | void __cdecl operator delete[ ] ( void* p, size_t n )
34 | {
35 | return free( p );
36 | }
37 |
38 | void __cdecl operator delete( void* p )
39 | {
40 | return free( p );
41 | }
42 |
43 | void* operator new( size_t, void* where )
44 | {
45 | return where;
46 | }
--------------------------------------------------------------------------------
/NtLisp/crt/misc.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "crt.h"
3 |
4 | void abort()
5 | {
6 | __debugbreak();
7 | }
8 |
9 | char* getenv()
10 | {
11 | return "virtual://";
12 | }
13 |
14 | typedef long clock_t;
15 |
16 | extern "C" clock_t clock()
17 | {
18 | ULARGE_INTEGER TickCount;
19 |
20 | while (TRUE)
21 | {
22 | TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
23 | TickCount.LowPart = SharedUserData->TickCount.LowPart;
24 |
25 | if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) break;
26 |
27 | YieldProcessor();
28 | }
29 |
30 | return (UInt32x32To64(TickCount.LowPart, SharedUserData->TickCountMultiplier) >> 24) +
31 | (UInt32x32To64(TickCount.HighPart, SharedUserData->TickCountMultiplier) << 8);
32 | }
33 |
34 | extern "C" time_t _time64(time_t* time)
35 | {
36 | LARGE_INTEGER SystemTime;
37 |
38 | do
39 | {
40 | SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
41 | SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
42 | } while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
43 |
44 | // https://www.gamedev.net/forums/topic/565693-converting-filetime-to-time_t-on-windows/
45 | return SystemTime.QuadPart / 10000000ULL - 11644473600ULL;
46 | }
--------------------------------------------------------------------------------
/NtLisp/crt/stdint.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | typedef unsigned __int8 uint8_t;
3 | typedef unsigned __int16 uint16_t;
4 | typedef unsigned __int32 uint32_t;
5 | typedef unsigned __int64 uint64_t;
6 | typedef __int8 int8_t;
7 | typedef __int16 int16_t;
8 | typedef __int32 int32_t;
9 | typedef __int64 int64_t;
--------------------------------------------------------------------------------
/NtLisp/crt/string.c:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "crt.h"
3 |
4 | int isalpha( int c )
5 | {
6 | return ( 'a' <= c && c <= 'z' ) ||
7 | ( 'A' <= c && c <= 'Z' );
8 | }
9 |
10 | int isdigit( int c )
11 | {
12 | return ( '0' <= c && c <= '9' );
13 | }
14 |
15 | int isalnum( int c )
16 | {
17 | return isalpha( c ) || isdigit( c );
18 | }
19 |
20 | int iscntrl( int c )
21 | {
22 | return c <= 0x1F || c == 0x7F;
23 | }
24 |
25 | int isgraph( int c )
26 | {
27 | return 0x21 <= c && c <= 0x7E;
28 | }
29 |
30 | int ispunct( int c )
31 | {
32 | for ( auto o : "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" )
33 | if ( o == c ) return 1;
34 | return 0;
35 | }
36 |
37 | double strtod( const char* str, const char** endptr )
38 | {
39 | double v = 0;
40 | if ( sscanf_s( str, "%lf", &v ) && endptr )
41 | *endptr = str + strlen( str );
42 | return v;
43 | }
44 |
45 | double atof( const char* str )
46 | {
47 | const char* endptr = 0;
48 | return strtod( str, &endptr );
49 | }
50 |
51 | char* strpbrk( const char* s1, const char* s2 )
52 | {
53 | while ( *s1 )
54 | if ( strchr( s2, *s1++ ) )
55 | return ( char* )--s1;
56 | return 0;
57 | }
58 |
59 | // haha locale go brrr
60 | //
61 | int strcoll( const char* a, const char* b )
62 | {
63 | return strcmp( a, b );
64 | }
--------------------------------------------------------------------------------
/NtLisp/driver_io.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Assuming the platform specific header is included already.
4 | #define NTLISP_RUN CTL_CODE( 0x13, 0x37, METHOD_BUFFERED, FILE_ANY_ACCESS )
5 |
6 | // Shared structures.
7 | //
8 | struct ntlisp_result
9 | {
10 | char* errors;
11 | char* outputs;
12 | };
--------------------------------------------------------------------------------
/NtLisp/logger.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | // Basic logger implementation.
5 | //
6 | namespace logger
7 | {
8 | struct string_buffer
9 | {
10 | static constexpr size_t buffer_length = 1024 * 1024 * 16;
11 |
12 | char raw[ buffer_length ];
13 | size_t iterator = 0;
14 |
15 | void append( const void* ptr, size_t n )
16 | {
17 | if ( ( iterator + n ) < buffer_length )
18 | {
19 | memcpy( raw + iterator, ptr, n );
20 | iterator += n;
21 | }
22 | }
23 |
24 | void reset()
25 | {
26 | iterator = 0;
27 | }
28 | };
29 |
30 | inline string_buffer logs = {};
31 | inline string_buffer errors = {};
32 |
33 | template
34 | static auto error( const char* format, T... args )
35 | {
36 | char buffer[ 512 ];
37 | size_t n = sprintf_s( buffer, 512, format, args... );
38 | errors.append( buffer, n );
39 | return n;
40 | }
41 | template
42 | static auto log( const char* format, T... args )
43 | {
44 | char buffer[ 512 ];
45 | size_t n = sprintf_s( buffer, 512, format, args... );
46 | logs.append( buffer, n );
47 | return n;
48 | }
49 | };
--------------------------------------------------------------------------------
/NtLisp/main.cpp:
--------------------------------------------------------------------------------
1 | #include "crt/crt.h"
2 | #include
3 | #include "logger.hpp"
4 | #include "driver_io.hpp"
5 | extern "C"
6 | {
7 | #include
8 | }
9 |
10 | // Global Lisp context.
11 | //
12 | static LispContext ctx;
13 |
14 | // Device control handler.
15 | //
16 | static NTSTATUS device_control( PDEVICE_OBJECT device_object, PIRP irp )
17 | {
18 | // If current control code is NTLUA_RUN:
19 | //
20 | PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation( irp );
21 | if ( irp_sp->Parameters.DeviceIoControl.IoControlCode == NTLISP_RUN )
22 | {
23 | const char* input = ( const char* ) irp->AssociatedIrp.SystemBuffer;
24 | ntlisp_result* result = ( ntlisp_result* ) irp->AssociatedIrp.SystemBuffer;
25 |
26 | size_t input_length = irp_sp->Parameters.DeviceIoControl.InputBufferLength;
27 | size_t output_length = irp_sp->Parameters.DeviceIoControl.OutputBufferLength;
28 |
29 | // Begin output size at 0.
30 | //
31 | irp->IoStatus.Information = 0;
32 |
33 | // If there is a valid, null-terminated buffer:
34 | //
35 | if ( input && input_length && input[ input_length - 1 ] == 0x0 )
36 | {
37 | // Execute the code in the buffer.
38 | //
39 | LispError error;
40 | Lisp program = lisp_read(input, &error, ctx);
41 | if (error == LISP_ERROR_NONE)
42 | {
43 | // execute program using global environment
44 | Lisp lisp_result = lisp_eval(program, &error, ctx);
45 | if (error == LISP_ERROR_NONE)
46 | {
47 | // Print the result
48 | lisp_print(lisp_result);
49 |
50 | // Garbage collect
51 | lisp_collect(lisp_make_null(), ctx);
52 | }
53 | else
54 | {
55 | logger::error("lisp_eval error: %s\n", lisp_error_string(error));
56 | }
57 | }
58 | else
59 | {
60 | logger::error("lisp_read error: %s\n", lisp_error_string(error));
61 | }
62 |
63 | // Zero out the result.
64 | //
65 | result->errors = nullptr;
66 | result->outputs = nullptr;
67 |
68 | // Declare a helper exporting the buffer from KM memory to UM memory.
69 | //
70 | const auto export_buffer = [ ] ( logger::string_buffer& buf )
71 | {
72 | // Allocate user-mode memory to hold this buffer.
73 | //
74 | void* region = nullptr;
75 | size_t size = buf.iterator;
76 | ZwAllocateVirtualMemory( NtCurrentProcess(), ( void** ) ®ion, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
77 |
78 | // Copy the buffer if allocation was succesful.
79 | //
80 | if ( region )
81 | {
82 | __try
83 | {
84 | memcpy( region, buf.raw, buf.iterator );
85 | }
86 | __except ( 1 )
87 | {
88 |
89 | }
90 | }
91 |
92 | // Reset the buffer and return the newly allocated region.
93 | //
94 | buf.reset();
95 | return ( char* ) region;
96 | };
97 |
98 | // If we have a valid output buffer:
99 | //
100 | if ( output_length >= sizeof( ntlisp_result ) )
101 | {
102 | if ( logger::errors.iterator )
103 | result->errors = export_buffer( logger::errors );
104 | if ( logger::logs.iterator )
105 | result->outputs = export_buffer( logger::logs );
106 | irp->IoStatus.Information = sizeof( ntlisp_result );
107 | }
108 |
109 | // Reset logger buffers.
110 | //
111 | logger::errors.reset();
112 | logger::logs.reset();
113 | }
114 |
115 | // Declare success and return.
116 | //
117 | irp->IoStatus.Status = STATUS_SUCCESS;
118 | IoCompleteRequest( irp, IO_NO_INCREMENT );
119 | return STATUS_SUCCESS;
120 | }
121 | else
122 | {
123 | // Report failure.
124 | //
125 | irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
126 | IoCompleteRequest( irp, IO_NO_INCREMENT );
127 | return STATUS_UNSUCCESSFUL;
128 | }
129 | }
130 |
131 | // Unloads the driver.
132 | //
133 | static void unload_driver( PDRIVER_OBJECT driver )
134 | {
135 | // Destroy the Lisp context.
136 | //
137 | lisp_shutdown(ctx);
138 |
139 | // Delete the symbolic link.
140 | //
141 | UNICODE_STRING sym_link;
142 | RtlInitUnicodeString( &sym_link, L"\\DosDevices\\NtLisp" );
143 | IoDeleteSymbolicLink( &sym_link );
144 |
145 | // Delete the device object.
146 | //
147 | if ( PDEVICE_OBJECT device_object = driver->DeviceObject )
148 | IoDeleteDevice( device_object );
149 | }
150 |
151 | // Execute corporate-level security check.
152 | //
153 | static NTSTATUS security_check( PDEVICE_OBJECT device_object, PIRP irp )
154 | {
155 | irp->IoStatus.Status = STATUS_SUCCESS;
156 | irp->IoStatus.Information = 0;
157 | IoCompleteRequest( irp, IO_NO_INCREMENT );
158 | return STATUS_SUCCESS;
159 | }
160 |
161 | // Entry-point.
162 | //
163 | extern "C" NTSTATUS DriverEntry( DRIVER_OBJECT* DriverObject, UNICODE_STRING* RegistryPath )
164 | {
165 | // Run static initializers.
166 | //
167 | crt::initialize();
168 |
169 | // Create a device object.
170 | //
171 | UNICODE_STRING device_name;
172 | RtlInitUnicodeString( &device_name, L"\\Device\\NtLisp" );
173 |
174 | PDEVICE_OBJECT device_object;
175 | NTSTATUS nt_status = IoCreateDevice
176 | (
177 | DriverObject,
178 | 0,
179 | &device_name,
180 | FILE_DEVICE_UNKNOWN,
181 | FILE_DEVICE_SECURE_OPEN,
182 | FALSE,
183 | &device_object
184 | );
185 | if ( !NT_SUCCESS( nt_status ) )
186 | return nt_status;
187 |
188 | // Set callbacks.
189 | //
190 | DriverObject->DriverUnload = &unload_driver;
191 | DriverObject->MajorFunction[ IRP_MJ_CREATE ] = &security_check;
192 | DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = &security_check;
193 | DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = &device_control;
194 |
195 | // Create a symbolic link.
196 | //
197 | UNICODE_STRING dos_device;
198 | RtlInitUnicodeString( &dos_device, L"\\DosDevices\\NtLisp" );
199 | nt_status = IoCreateSymbolicLink( &dos_device, &device_name );
200 | if ( !NT_SUCCESS( nt_status ) )
201 | {
202 | IoDeleteDevice( device_object );
203 | return nt_status;
204 | }
205 |
206 | // Initialize Lisp.
207 | //
208 | ctx = lisp_init_lib();
209 | return STATUS_SUCCESS;
210 | }
--------------------------------------------------------------------------------
/NtLispRepl/NtLispRepl.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {82b12053-4da0-440b-8af4-55f49658299e}
25 | ActualConsole
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Level3
88 | true
89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
90 | true
91 |
92 |
93 | Console
94 | true
95 |
96 |
97 |
98 |
99 | Level3
100 | true
101 | true
102 | true
103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
104 | true
105 |
106 |
107 | Console
108 | true
109 | true
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
118 | true
119 | MultiThreadedDebug
120 | stdcpplatest
121 |
122 |
123 | Console
124 | true
125 |
126 |
127 |
128 |
129 | Level3
130 | true
131 | true
132 | true
133 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
134 | true
135 | MultiThreaded
136 | stdcpplatest
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/NtLispRepl/NtLispRepl.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/NtLispRepl/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "../NtLisp/driver_io.hpp"
7 |
8 | int main()
9 | {
10 | // Create a handle to the device.
11 | //
12 | HANDLE device = CreateFileA
13 | (
14 | "\\\\.\\NtLisp",
15 | GENERIC_READ | GENERIC_WRITE,
16 | FILE_SHARE_READ | FILE_SHARE_WRITE,
17 | NULL,
18 | OPEN_EXISTING,
19 | FILE_ATTRIBUTE_NORMAL,
20 | NULL
21 | );
22 | if ( device == INVALID_HANDLE_VALUE ) return 1;
23 |
24 | // Enter REPL:
25 | //
26 | while ( 1 )
27 | {
28 | // Reset colors and ask user for input.
29 | //
30 | SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 7 );
31 | std::string buffer;
32 | std::cout << "=> ";
33 | std::getline( std::cin, buffer );
34 |
35 | // While shift is being held, allow multiple lines to be inputted.
36 | //
37 | while ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
38 | {
39 | std::string buffer2;
40 | std::cout << " ";
41 | std::getline( std::cin, buffer2 );
42 | buffer += "\n" + buffer2;
43 | }
44 |
45 | // Send IOCTL.
46 | //
47 | ntlisp_result result = {
48 | nullptr,
49 | nullptr
50 | };
51 |
52 | DWORD discarded = 0;
53 | DeviceIoControl(
54 | device,
55 | NTLISP_RUN,
56 | &buffer[0], buffer.size() + 1,
57 | &result, sizeof( result ),
58 | &discarded, nullptr
59 | );
60 |
61 | // Print each buffer if relevant.
62 | //
63 | for ( auto& [buffer, color] : { std::pair{ result.errors, 12 },
64 | std::pair{ result.outputs, 15 } } )
65 | {
66 | if ( !buffer ) continue;
67 | SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), color );
68 | puts( buffer );
69 | VirtualFree( buffer, 0, MEM_RELEASE );
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NtLisp
2 |
3 | Since [NtLua](https://github.com/can1357/NtLua) and [NtPhp](https://github.com/mrexodia/NtPhp) there has been an insatiable desire for more scripting languages in the kernel, so here is [lisp](https://github.com/justinmeiners/lisp-interpreter) in the kernel!
4 |
5 | ## 
6 |
--------------------------------------------------------------------------------
/vmware_03-17-34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrexodia/NtLisp/41916fade5525aad448e2a602746d93fcef7d14d/vmware_03-17-34.png
--------------------------------------------------------------------------------