├── .idea └── vcs.xml ├── CMakeLists.txt ├── Console ├── Headers │ ├── config.h │ ├── console.h │ ├── cursor.h │ ├── display.h │ ├── expr.h │ ├── font.h │ ├── key.h │ ├── line.h │ ├── misc.h │ ├── node.h │ ├── string.h │ └── symbol.h ├── Resources │ └── sys_font.bmp └── Sources │ ├── console.cpp │ ├── cursor.cpp │ ├── display.cpp │ ├── expr.cpp │ ├── font.cpp │ ├── key_glfw.cpp │ ├── line.cpp │ ├── node.cpp │ ├── string.cpp │ └── symbol.cpp ├── Eigenmath ├── Headers │ ├── defs.h │ ├── help.h │ ├── prototypes.h │ ├── selftest.h │ └── stdafx.h └── Sources │ ├── abs.cpp │ ├── add.cpp │ ├── adj.cpp │ ├── alloc.cpp │ ├── append.cpp │ ├── arccos.cpp │ ├── arccosh.cpp │ ├── arcsin.cpp │ ├── arcsinh.cpp │ ├── arctan.cpp │ ├── arctanh.cpp │ ├── arg.cpp │ ├── atomize.cpp │ ├── bake.cpp │ ├── besselj.cpp │ ├── bessely.cpp │ ├── bignum.cpp │ ├── binomial.cpp │ ├── ceiling.cpp │ ├── choose.cpp │ ├── circexp.cpp │ ├── clear.cpp │ ├── clock.cpp │ ├── coeff.cpp │ ├── cofactor.cpp │ ├── condense.cpp │ ├── conj.cpp │ ├── cons.cpp │ ├── contract.cpp │ ├── cos.cpp │ ├── cosh.cpp │ ├── data.cpp │ ├── decomp.cpp │ ├── define.cpp │ ├── defint.cpp │ ├── degree.cpp │ ├── denominator.cpp │ ├── derivative.cpp │ ├── det.cpp │ ├── dirac.cpp │ ├── display.cpp │ ├── distill.cpp │ ├── divisors.cpp │ ├── dpow.cpp │ ├── dsolve.cpp │ ├── eigen.cpp │ ├── eigenmath.cpp │ ├── erf.cpp │ ├── erfc.cpp │ ├── eval.cpp │ ├── expand.cpp │ ├── expcos.cpp │ ├── expsin.cpp │ ├── factor.cpp │ ├── factorial.cpp │ ├── factorpoly.cpp │ ├── factors.cpp │ ├── filter.cpp │ ├── find.cpp │ ├── float.cpp │ ├── floor.cpp │ ├── for.cpp │ ├── gamma.cpp │ ├── gcd.cpp │ ├── guess.cpp │ ├── hermite.cpp │ ├── hilbert.cpp │ ├── imag.cpp │ ├── index.cpp │ ├── init.cpp │ ├── inner.cpp │ ├── integral.cpp │ ├── inv.cpp │ ├── is.cpp │ ├── isprime.cpp │ ├── itab.cpp │ ├── itest.cpp │ ├── laguerre.cpp │ ├── laplace.cpp │ ├── lcm.cpp │ ├── leading.cpp │ ├── legendre.cpp │ ├── list.cpp │ ├── log.cpp │ ├── madd.cpp │ ├── mag.cpp │ ├── mcmp.cpp │ ├── mfactor.cpp │ ├── mgcd.cpp │ ├── mini-test.cpp │ ├── misc.cpp │ ├── mmodpow.cpp │ ├── mmul.cpp │ ├── mod.cpp │ ├── mpow.cpp │ ├── mprime.cpp │ ├── mroot.cpp │ ├── mscan.cpp │ ├── msqrt.cpp │ ├── mstr.cpp │ ├── multiply.cpp │ ├── nroots.cpp │ ├── numerator.cpp │ ├── outer.cpp │ ├── partition.cpp │ ├── polar.cpp │ ├── pollard.cpp │ ├── power.cpp │ ├── prime.cpp │ ├── primetab.cpp │ ├── print.cpp │ ├── product.cpp │ ├── qadd.cpp │ ├── qdiv.cpp │ ├── qmul.cpp │ ├── qpow.cpp │ ├── qsub.cpp │ ├── quickfactor.cpp │ ├── quotient.cpp │ ├── rationalize.cpp │ ├── real.cpp │ ├── rect.cpp │ ├── rewrite.cpp │ ├── roots.cpp │ ├── run.cpp │ ├── scan.cpp │ ├── selftest.cpp │ ├── sgn.cpp │ ├── simfac.cpp │ ├── simplify.cpp │ ├── sin.cpp │ ├── sinh.cpp │ ├── stack.cpp │ ├── subst.cpp │ ├── sum.cpp │ ├── symbol.cpp │ ├── tan.cpp │ ├── tanh.cpp │ ├── taylor.cpp │ ├── tensor.cpp │ ├── test.cpp │ ├── transform.cpp │ ├── transpose.cpp │ ├── userfunc.cpp │ ├── variables.cpp │ ├── vectorize.cpp │ └── zero.cpp ├── README.md ├── Shots ├── 01.png ├── 02.png └── on_calc.bmp ├── _config.yml ├── graphics.h └── main.cpp /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | project(Console-fx) 3 | 4 | set(CMAKE_CXX_STANDARD 98) 5 | 6 | file(GLOB_RECURSE CONSOLE_SOURCES "Console/Sources/*.cpp") 7 | file(GLOB_RECURSE CONSOLE_HEADERS "Console/Headers/*.h") 8 | 9 | file(GLOB_RECURSE EIGENMATH_HEADERS "Eigenmath/Headers/*.h") 10 | file(GLOB_RECURSE EIGENMATH_SOURCES "Eigenmath/Sources/*.cpp") 11 | 12 | set(SOURCE_FILES main.cpp graphics.h ${CONSOLE_HEADERS} ${CONSOLE_SOURCES} ${EIGENMATH_HEADERS} ${EIGENMATH_SOURCES}) 13 | add_executable(${PROJECT_NAME} ${SOURCE_FILES}) 14 | 15 | find_package(glfw3 REQUIRED) 16 | find_package(OpenGL REQUIRED) 17 | target_link_libraries(${PROJECT_NAME} glfw OpenGL::GL) 18 | -------------------------------------------------------------------------------- /Console/Headers/config.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/16. 3 | // 4 | 5 | #ifndef CONSOLE_FX_CONFIG_H 6 | #define CONSOLE_FX_CONFIG_H 7 | 8 | #define SCREEN_WIDTH 512 9 | #define SCREEN_HEIGHT 256 10 | #define SCREEN_WIDTH_BYTE ((SCREEN_WIDTH + 7) >> 3) 11 | #define VRAM_SIZE_BYTE (SCREEN_WIDTH_BYTE * SCREEN_HEIGHT) 12 | 13 | #define FONT_WIDTH 6 14 | #define FONT_HEIGHT 4 15 | #define FONT_DEPTH 4 16 | #define FONT_SIZE_BYTE 8 17 | 18 | #define LINE_QUEUE_CAPACITY 256 19 | #define STRING_CAPACITY_BLOCK 8 20 | 21 | #endif //CONSOLE_FX_CONFIG_H 22 | -------------------------------------------------------------------------------- /Console/Headers/console.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/7. 3 | // 4 | 5 | #ifndef CONSOLE_FX_CONSOLE_H 6 | #define CONSOLE_FX_CONSOLE_H 7 | 8 | #include "config.h" 9 | #include "string.h" 10 | #include "line.h" 11 | #include "cursor.h" 12 | #include "display.h" 13 | #include "key.h" 14 | 15 | namespace fx 16 | { 17 | class Console 18 | { 19 | private: 20 | int _line_start; 21 | int _line_end; 22 | int _line_count; 23 | Line *_line_queue[LINE_QUEUE_CAPACITY]; 24 | Cursor _cursor; 25 | Display _display; 26 | int _offset; 27 | 28 | void pop_line(void); 29 | Line *add_line(LineType type, bool editable); 30 | 31 | void render(void); 32 | 33 | public: 34 | Console(unsigned char *vram); 35 | ~Console(void); 36 | String &input(String &str_input); 37 | void output(const String &str_output); 38 | }; 39 | } 40 | 41 | #endif //CONSOLE_FX_CONSOLE_H 42 | -------------------------------------------------------------------------------- /Console/Headers/cursor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/13. 3 | // 4 | 5 | #ifndef CONSOLE_FX_CURSOR_H 6 | #define CONSOLE_FX_CURSOR_H 7 | 8 | #include "expr.h" 9 | #include "line.h" 10 | #include "config.h" 11 | 12 | namespace fx 13 | { 14 | enum CursorStatus 15 | { 16 | CURSOR_EDITING, 17 | CURSOR_SELECTING 18 | }; 19 | 20 | class Cursor 21 | { 22 | private: 23 | CursorStatus _status; 24 | Line *_curr_line; 25 | Expr *_curr_expr; 26 | Node *_curr_node; 27 | int _x; 28 | int _y; 29 | int _length; 30 | int _pos; 31 | bool _visible; 32 | 33 | public: 34 | Cursor(void) : _curr_line(NULL), _curr_expr(NULL), _curr_node(NULL), _visible(true), _x(0), _y(0), _length(7), _status(CURSOR_EDITING) {} 35 | Line *curr_line(void) const { return _curr_line; } 36 | Expr *curr_expr(void) const { return _curr_expr; } 37 | Node *curr_node(void) const { return _curr_node; } 38 | CursorStatus status(void) const { return _status; } 39 | bool visible(void) const { return _visible; } 40 | void flash(void) { _visible = !_visible; } 41 | int pos(void) const { return _pos; } 42 | int x(void) const { return _x; } 43 | int y(void) const { return _y; } 44 | int length(void) const { return _length; } 45 | void set_x(int left) { _x = left; } 46 | void set_y(int top) { _y = top; } 47 | void set_length(int length) { _length = length; } 48 | void goto_line(Line *line); 49 | void move_left(void); 50 | void move_right(void); 51 | void insert(SymbolType type, const char *c_str = ""); 52 | void clear_line(void); 53 | void backspace(void); 54 | }; 55 | } 56 | 57 | #endif //CONSOLE_FX_CURSOR_H 58 | -------------------------------------------------------------------------------- /Console/Headers/display.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/12. 3 | // 4 | 5 | #ifndef CONSOLE_FX_DISPLAY_H 6 | #define CONSOLE_FX_DISPLAY_H 7 | 8 | #include "config.h" 9 | #include "string.h" 10 | #include "symbol.h" 11 | #include "expr.h" 12 | #include "line.h" 13 | #include "cursor.h" 14 | 15 | namespace fx 16 | { 17 | class Display 18 | { 19 | private: 20 | unsigned char *_vram; 21 | Cursor *_cursor; 22 | 23 | public: 24 | Display(unsigned char *vram, Cursor &cursor) : _vram(vram), _cursor(&cursor) {} 25 | bool on_screen(int x, int y) const { return (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT); } 26 | const unsigned char *vram(void) { return _vram; } 27 | bool test_point(int x, int y) { return on_screen(x, y) ? (bool)(_vram[(y * SCREEN_WIDTH_BYTE) + (x >> 3)] & (128 >> (x & 7))) : false; } 28 | void draw_point(int x, int y) { if (on_screen(x, y)) _vram[(y * SCREEN_WIDTH_BYTE) + (x >> 3)] |= 128 >> (x & 7); } 29 | void clear_point(int x, int y) { if (on_screen(x, y)) _vram[(y * SCREEN_WIDTH_BYTE) + (x >> 3)] &= ~(128 >> (x & 7)); } 30 | void reverse_point(int x, int y) { if (on_screen(x, y)) _vram[(y * SCREEN_WIDTH_BYTE) + (x >> 3)] ^= 128 >> (x & 7); } 31 | void draw_bitmap(const unsigned char *bmp, int x, int y, int width, int height); 32 | void draw_line(int x1, int y1, int x2, int y2); 33 | void clear_line(int x1, int y1, int x2, int y2); 34 | void reverse_line(int x1, int y1, int x2, int y2); 35 | void fill_area(int left, int top, int right, int bottom); 36 | void clear_area(int left, int top, int right, int bottom); 37 | void reverse_area(int left, int top, int right, int bottom); 38 | void fill_all(void); 39 | void clear_all(void); 40 | void reverse_all(void); 41 | void draw_cursor(int left, int base, int height, int depth); 42 | void print_char(int code, int left, int top); 43 | void print_str(const String &str, int left, int top); 44 | void print_c_str(const char *c_str, int left, int top); 45 | void print_symbol(const Symbol &symbol, int left, int base); 46 | void print_expr(const Expr &expr, int left, int base); 47 | void print_line(const Line &line, int offset); 48 | }; 49 | } 50 | 51 | #endif //CONSOLE_FX_DISPLAY_H 52 | -------------------------------------------------------------------------------- /Console/Headers/expr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/12. 3 | // 4 | 5 | #ifndef CONSOLE_FX_EXPR_H 6 | #define CONSOLE_FX_EXPR_H 7 | 8 | #include "string.h" 9 | #include "symbol.h" 10 | #include "node.h" 11 | 12 | namespace fx 13 | { 14 | class Expr 15 | { 16 | private: 17 | Node *_node_list; 18 | Node *_parent; 19 | 20 | int _width; 21 | int _height; 22 | int _depth; 23 | 24 | public: 25 | Expr(Node *parent = NULL); 26 | Expr(const char *c_str, size_t start_pos, size_t end_pos); 27 | ~Expr(void); 28 | Node *last(void) const; 29 | Node *head(void) const { return _node_list; } 30 | Node *parent(void) const { return _parent; } 31 | int width(void) const { return _width; } 32 | int height(void) const { return _height; } 33 | int depth(void) const { return _depth; } 34 | bool empty(void) const { return (_node_list->next() == NULL); } 35 | void set_parent(Node *parent); 36 | int calc_width(void); 37 | int calc_height(void); 38 | int calc_depth(void); 39 | void clear(void); 40 | String &to_str(String &result) const; 41 | }; 42 | } 43 | 44 | #endif //CONSOLE_FX_EXPR_H 45 | -------------------------------------------------------------------------------- /Console/Headers/font.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/12. 3 | // 4 | 5 | #ifndef CONSOLE_FX_FONT_H 6 | #define CONSOLE_FX_FONT_H 7 | 8 | #include "config.h" 9 | 10 | namespace fx 11 | { 12 | const unsigned char *GetFontBitmap(int code = 0); 13 | } 14 | 15 | #endif //CONSOLE_FX_FONT_H 16 | -------------------------------------------------------------------------------- /Console/Headers/key.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/16. 3 | // 4 | 5 | #ifndef CONSOLE_FX_KEY_H 6 | #define CONSOLE_FX_KEY_H 7 | 8 | namespace fx 9 | { 10 | enum ControlCode 11 | { 12 | CONTROL_EXE = 0xaf0000, 13 | CONTROL_DEL, 14 | CONTROL_AC, 15 | CONTROL_UP, 16 | CONTROL_DOWN, 17 | CONTROL_LEFT, 18 | CONTROL_RIGHT 19 | }; 20 | 21 | enum VariableCode 22 | { 23 | VARIABLE_ANS = 0xbf0000, 24 | VARIABLE_PI, 25 | VARIABLE_THETA 26 | }; 27 | 28 | enum FunctionCode 29 | { 30 | FUNCTION_SQUARE = 0xcf0000, 31 | FUNCTION_POWER_10, 32 | FUNCTION_POWER_E, 33 | FUNCTION_LN, 34 | FUNCTION_SIN, 35 | FUNCTION_COS, 36 | FUNCTION_TAN, 37 | FUNCTION_ARCSIN, 38 | FUNCTION_ARCCOS, 39 | FUNCTION_ARCTAN, 40 | FUNCTION_RECIPROCAL, 41 | FUNCTION_CUBEROOT, 42 | FUNCTION_FLOAT, 43 | FUNCTION_EXP, 44 | FUNCTION_SIMPLIFY 45 | }; 46 | 47 | int GetKeycode(void); 48 | } 49 | 50 | #endif //CONSOLE_FX_KEY_H 51 | -------------------------------------------------------------------------------- /Console/Headers/line.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/14. 3 | // 4 | 5 | #ifndef CONSOLE_FX_LINE_H 6 | #define CONSOLE_FX_LINE_H 7 | 8 | #include "expr.h" 9 | 10 | namespace fx 11 | { 12 | enum LineType 13 | { 14 | LINE_INPUT, 15 | LINE_OUTPUT 16 | }; 17 | 18 | class Line 19 | { 20 | private: 21 | int _offset; 22 | int _scroll; 23 | bool _editable; 24 | Expr *_expr; 25 | LineType _type; 26 | 27 | public: 28 | Line(LineType type = LINE_INPUT, bool editable = true, int offset = 0) : _offset(offset), _scroll(0), _editable(editable), _type(type) { _expr = new Expr; } 29 | ~Line(void); 30 | int scroll(void) const { return _scroll; } 31 | int offset(void) const { return _offset; } 32 | int bottom(void) const { return (_offset + height() - 1); } 33 | Expr *expr(void) const { return _expr; } 34 | LineType type(void) const { return _type; } 35 | bool editable(void) const { return _editable; } 36 | int width(void) const { return _expr->width(); } 37 | int height(void) const { return (_expr->height() + _expr->depth()); } 38 | void set_offset(int top) { _offset = top; } 39 | void set_scroll(int scroll) { _scroll = scroll; } 40 | void set_editable(bool editable) { _editable = editable; } 41 | void set_type(LineType type) { _type = type; } 42 | void update(void) { _expr->calc_width(), _expr->calc_height(), _expr->calc_depth(); } 43 | }; 44 | } 45 | 46 | #endif //CONSOLE_FX_LINE_H 47 | -------------------------------------------------------------------------------- /Console/Headers/misc.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/12. 3 | // 4 | 5 | #ifndef CONSOLE_FX_MISC_H 6 | #define CONSOLE_FX_MISC_H 7 | 8 | namespace fx 9 | { 10 | template inline T abs(const T &x) { return (x > 0) ? x : -x; } 11 | 12 | template inline const T &max(const T &a, const T &b) { return (a > b) ? a : b; } 13 | 14 | template inline const T &min(const T &a, const T &b) { return (a < b) ? a : b; } 15 | 16 | template int sgn(const T &x) { return (x > 0) ? 1 : ((x < 0) ? -1 : 0); } 17 | 18 | template inline void swap(T &a, T &b) 19 | { 20 | T tmp = a; 21 | a = b, b = tmp; 22 | } 23 | 24 | template bool is_char(const T &c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')); } 25 | } 26 | 27 | #endif //CONSOLE_FX_MISC_H 28 | -------------------------------------------------------------------------------- /Console/Headers/node.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/14. 3 | // 4 | 5 | #ifndef CONSOLE_FX_NODE_H 6 | #define CONSOLE_FX_NODE_H 7 | 8 | #include "symbol.h" 9 | 10 | namespace fx 11 | { 12 | class Expr; 13 | 14 | class Node 15 | { 16 | private: 17 | Symbol *_symbol; 18 | Node *_prev; 19 | Node *_next; 20 | 21 | public: 22 | Node(Node *prev, Node *next, SymbolType type, const char *c_str = ""); 23 | Node(Symbol *parent_symbol) : _symbol(parent_symbol), _prev(NULL), _next(NULL) {} // Used only for constructing the head of a head. 24 | ~Node(void); 25 | Symbol *symbol(void) const { return _symbol; } 26 | Node *prev(void) const { return _prev; } 27 | Node *next(void) const { return _next; } 28 | void set_symbol(Symbol *symbol) { _symbol = symbol; } 29 | Node *append(SymbolType type = SYMBOL_STR, const char *c_str = ""); 30 | Node *append(const Expr *expr); 31 | Node *find_head(void) const; 32 | bool head_of_line(void) const { return (_symbol == NULL); } 33 | bool head_of_expr(void) const { return (_prev == NULL); } 34 | bool last_of_expr(void) const { return (_next == NULL); } 35 | }; 36 | } 37 | 38 | #endif //CONSOLE_FX_NODE_H 39 | -------------------------------------------------------------------------------- /Console/Headers/string.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/7. 3 | // 4 | 5 | #ifndef CONSOLE_FX_STRING_H 6 | #define CONSOLE_FX_STRING_H 7 | 8 | #include 9 | #include "config.h" 10 | 11 | namespace fx 12 | { 13 | class String 14 | { 15 | private: 16 | char *_c_str; 17 | size_t _size; 18 | size_t _capacity; 19 | 20 | public: 21 | String(size_t capacity = 0); 22 | String(const char *c_str); 23 | String(const String &str); 24 | ~String(void); 25 | 26 | size_t size(void) const { return _size; } 27 | const char *c_str(void) const { return _c_str; } 28 | 29 | String &clear(void); 30 | String &append(const char *c_str, size_t str_len = 0); 31 | String &append(const String &str); 32 | String &append(char c); 33 | String &backspace(size_t len = 1); 34 | String &insert(size_t pos, char c); 35 | String &insert(size_t pos, const char *c_str); 36 | String &insert(size_t pos, const String &str); 37 | String &remove(size_t pos, size_t len = 1); 38 | 39 | char operator[](size_t index) const { return (index < _size) ? _c_str[index] : (char)'\0'; } 40 | }; 41 | } 42 | 43 | #endif //CONSOLE_FX_STRING_H 44 | -------------------------------------------------------------------------------- /Console/Headers/symbol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/12. 3 | // 4 | 5 | #ifndef CONSOLE_FX_SYMBOL_H 6 | #define CONSOLE_FX_SYMBOL_H 7 | 8 | #include "string.h" 9 | 10 | namespace fx 11 | { 12 | class Node; 13 | class Expr; 14 | 15 | enum SymbolType 16 | { 17 | SYMBOL_HEAD = 0xfe0000, // Symbol in a head node. 18 | SYMBOL_ABS = 0xff0000, // Values start from 0xff0000 to avoid mixing with other keycode or ConsoleCode. 19 | SYMBOL_DEFINITE, 20 | SYMBOL_FRAC, 21 | SYMBOL_INTEGRAL, 22 | SYMBOL_LOG, 23 | SYMBOL_POWER, 24 | SYMBOL_PRODUCT, 25 | SYMBOL_ROOT, 26 | SYMBOL_SQRT, 27 | SYMBOL_STR, 28 | SYMBOL_SUM 29 | }; 30 | 31 | class Symbol 32 | { 33 | private: 34 | SymbolType _type; 35 | int _width; 36 | int _height; 37 | int _depth; 38 | union 39 | { 40 | String *_str; 41 | Expr *_arg_list; 42 | }; 43 | 44 | public: 45 | Symbol(Node *parent_node, SymbolType type, const char *c_str); 46 | ~Symbol(void); 47 | int width(void) const { return _width; } 48 | int height(void) const { return _height; } 49 | int depth(void) const { return _depth; } 50 | SymbolType type(void) const { return _type; } 51 | String &str(void) const { return *_str; } 52 | Expr *arg_list(void) const { return _arg_list; } 53 | Expr &arg(int index) const; 54 | int arg_index(const Expr *arg) const; 55 | int arg_index(const Expr &arg) const; 56 | int arg_count(void) const; 57 | int calc_width(void); 58 | int calc_height(void); 59 | int calc_depth(void); 60 | String &to_str(String &result) const; 61 | }; 62 | } 63 | 64 | #endif //CONSOLE_FX_SYMBOL_H 65 | -------------------------------------------------------------------------------- /Console/Resources/sys_font.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mike-Leo-Smith/Console-fx/a965a967b4411d3529fa8152d0cdc88b5e2be3b5/Console/Resources/sys_font.bmp -------------------------------------------------------------------------------- /Console/Sources/key_glfw.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/16. 3 | // 4 | 5 | #include 6 | #include "../../graphics.h" 7 | #include "../Headers/key.h" 8 | #include "../Headers/symbol.h" 9 | 10 | namespace fx 11 | { 12 | // Platform-specific function, need to be implemented by yourself. 13 | int GetKeycode(void) 14 | { 15 | DisplayVRAM(); 16 | glfwWaitEventsTimeout(1); 17 | 18 | if (glfwGetKey(win, GLFW_KEY_LEFT_SHIFT)) 19 | { 20 | if (glfwGetKey(win, '1')) 21 | { 22 | return '!'; 23 | } 24 | 25 | if (glfwGetKey(win, '6')) 26 | { 27 | return SYMBOL_POWER; 28 | } 29 | 30 | if (glfwGetKey(win, '8')) 31 | { 32 | return '*'; 33 | } 34 | 35 | if (glfwGetKey(win, '9')) 36 | { 37 | return '('; 38 | } 39 | 40 | if (glfwGetKey(win, '0')) 41 | { 42 | return ')'; 43 | } 44 | 45 | if (glfwGetKey(win, '=')) 46 | { 47 | return '+'; 48 | } 49 | 50 | if (glfwGetKey(win, ',')) 51 | { 52 | return '<'; 53 | } 54 | 55 | if (glfwGetKey(win, '.')) 56 | { 57 | return '>'; 58 | } 59 | 60 | if (glfwGetKey(win, '\'')) 61 | { 62 | return '\"'; 63 | } 64 | } 65 | 66 | for (int i = 0; i <= 0x7f; i++) 67 | { 68 | if (glfwGetKey(win, i)) 69 | { 70 | if (i >= 'A' && i <= 'Z') 71 | { 72 | if (glfwGetKey(win, GLFW_KEY_LEFT_SHIFT)) 73 | { 74 | return i; 75 | } 76 | else 77 | { 78 | return i - 'A' + 'a'; 79 | } 80 | } 81 | else 82 | { 83 | return i; 84 | } 85 | } 86 | } 87 | 88 | if (glfwGetKey(win, GLFW_KEY_ENTER)) 89 | { 90 | return CONTROL_EXE; 91 | } 92 | 93 | if (glfwGetKey(win, GLFW_KEY_RIGHT)) 94 | { 95 | return CONTROL_RIGHT; 96 | } 97 | 98 | if (glfwGetKey(win, GLFW_KEY_LEFT)) 99 | { 100 | return CONTROL_LEFT; 101 | } 102 | 103 | if (glfwGetKey(win, GLFW_KEY_UP)) 104 | { 105 | return CONTROL_UP; 106 | } 107 | 108 | if (glfwGetKey(win, GLFW_KEY_DOWN)) 109 | { 110 | return CONTROL_DOWN; 111 | } 112 | 113 | if (glfwGetKey(win, GLFW_KEY_LEFT_ALT)) 114 | { 115 | return CONTROL_AC; 116 | } 117 | 118 | if (glfwGetKey(win, GLFW_KEY_BACKSPACE)) 119 | { 120 | return CONTROL_DEL; 121 | } 122 | 123 | for (int i = GLFW_KEY_F1; i <= GLFW_KEY_F11; i++) 124 | { 125 | if (glfwGetKey(win, i)) 126 | { 127 | return SYMBOL_ABS + i - GLFW_KEY_F1; 128 | } 129 | } 130 | 131 | return 0; 132 | } 133 | } -------------------------------------------------------------------------------- /Console/Sources/line.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/14. 3 | // 4 | 5 | #include "../Headers/line.h" 6 | 7 | namespace fx 8 | { 9 | 10 | Line::~Line(void) 11 | { 12 | if (_expr != NULL) 13 | { 14 | delete _expr; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Console/Sources/node.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/14. 3 | // 4 | 5 | #include "../Headers/node.h" 6 | #include "../Headers/expr.h" 7 | 8 | namespace fx 9 | { 10 | Node::Node(Node *prev, Node *next, SymbolType type, const char *c_str) : _prev(prev), _next(next) 11 | { 12 | _symbol = new Symbol(this, type, c_str); 13 | } 14 | 15 | Node::~Node(void) 16 | { 17 | if (_prev != NULL) 18 | { 19 | _prev->_next = _next; 20 | } 21 | else 22 | { 23 | delete _symbol; 24 | } 25 | 26 | if (_next != NULL) 27 | { 28 | _next->_prev = _prev; 29 | } 30 | } 31 | 32 | Node *Node::append(SymbolType type, const char *c_str) 33 | { 34 | Node *new_node = new Node(this, _next, type, c_str); 35 | 36 | if (_next != NULL) 37 | { 38 | _next->_prev = new_node; 39 | } 40 | _next = new_node; 41 | 42 | return new_node; 43 | } 44 | 45 | Node *Node::find_head(void) const 46 | { 47 | Node *ptr; 48 | 49 | for (ptr = (Node *)this; ptr->_prev != NULL; ptr = ptr->prev()); 50 | 51 | return ptr; 52 | } 53 | 54 | Node *Node::append(const Expr *expr) 55 | { 56 | Node *ptr; 57 | 58 | for (ptr = expr->head()->next(); ptr != NULL; ptr = ptr->next()) 59 | { 60 | if (ptr->symbol()->type() == SYMBOL_STR) 61 | { 62 | append(SYMBOL_STR, ptr->symbol()->str().c_str()); 63 | } 64 | else 65 | { 66 | int arg_count = ptr->symbol()->arg_count(); 67 | 68 | append(ptr->symbol()->type()); 69 | for (int i = 0; i < arg_count; i++) 70 | { 71 | _next->symbol()->arg(i).head()->append(&ptr->symbol()->arg(i)); 72 | } 73 | } 74 | } 75 | 76 | if (_next != NULL) 77 | { 78 | return _next; 79 | } 80 | else 81 | { 82 | return this; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /Eigenmath/Headers/stdafx.h: -------------------------------------------------------------------------------- 1 | // Required by VC++. 2 | -------------------------------------------------------------------------------- /Eigenmath/Sources/abs.cpp: -------------------------------------------------------------------------------- 1 | // Absolute value, aka vector magnitude 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_abs(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | absval(); 11 | } 12 | 13 | void 14 | absval(void) 15 | { 16 | int h; 17 | save(); 18 | p1 = pop(); 19 | 20 | if (istensor(p1)) 21 | { 22 | absval_tensor(); 23 | restore(); 24 | return; 25 | } 26 | 27 | if (isnum(p1)) 28 | { 29 | push(p1); 30 | if (isnegativenumber(p1)) 31 | negate(); 32 | restore(); 33 | return; 34 | } 35 | 36 | if (iscomplexnumber(p1)) 37 | { 38 | push(p1); 39 | push(p1); 40 | conjugate(); 41 | multiply(); 42 | push_rational(1, 2); 43 | power(); 44 | restore(); 45 | return; 46 | } 47 | 48 | // abs(1/a) evaluates to 1/abs(a) 49 | 50 | if (car(p1) == symbol(POWER) && isnegativeterm(caddr(p1))) 51 | { 52 | push(p1); 53 | reciprocate(); 54 | absval(); 55 | reciprocate(); 56 | restore(); 57 | return; 58 | } 59 | 60 | // abs(a*b) evaluates to abs(a)*abs(b) 61 | 62 | if (car(p1) == symbol(MULTIPLY)) 63 | { 64 | h = tos; 65 | p1 = cdr(p1); 66 | while (iscons(p1)) 67 | { 68 | push(car(p1)); 69 | absval(); 70 | p1 = cdr(p1); 71 | } 72 | multiply_all(tos - h); 73 | restore(); 74 | return; 75 | } 76 | 77 | if (isnegativeterm(p1) || (car(p1) == symbol(ADD) && isnegativeterm(cadr(p1)))) 78 | { 79 | push(p1); 80 | negate(); 81 | p1 = pop(); 82 | } 83 | 84 | push_symbol(ABS); 85 | push(p1); 86 | list(2); 87 | 88 | restore(); 89 | } 90 | 91 | void 92 | absval_tensor(void) 93 | { 94 | if (p1->u.tensor->ndim != 1) 95 | stop("abs(tensor) with tensor rank > 1"); 96 | push(p1); 97 | push(p1); 98 | conjugate(); 99 | inner(); 100 | push_rational(1, 2); 101 | power(); 102 | simplify(); 103 | eval(); 104 | } 105 | 106 | #if SELFTEST 107 | 108 | static char *s[] = { 109 | 110 | "abs(2)", 111 | "2", 112 | 113 | "abs(2.0)", 114 | "2", 115 | 116 | "abs(-2)", 117 | "2", 118 | 119 | "abs(-2.0)", 120 | "2", 121 | 122 | "abs(a)", 123 | "abs(a)", 124 | 125 | "abs(-a)", 126 | "abs(a)", 127 | 128 | "abs(2*a)", 129 | "2*abs(a)", 130 | 131 | "abs(-2*a)", 132 | "2*abs(a)", 133 | 134 | "abs(2.0*a)", 135 | "2*abs(a)", 136 | 137 | "abs(-2.0*a)", 138 | "2*abs(a)", 139 | 140 | "abs(a-b)+abs(b-a)", 141 | "2*abs(a-b)", 142 | 143 | "abs(3 + 4 i)", 144 | "5", 145 | 146 | "abs((2,3,4))", 147 | "29^(1/2)", 148 | 149 | "abs(a*b)", 150 | "abs(a)*abs(b)", 151 | 152 | "abs(a/b)", 153 | "abs(a)/abs(b)", 154 | 155 | "abs(1/a^b)", 156 | "1/(abs(a^b))", 157 | 158 | // Check that vector length is simplified 159 | 160 | "P=(u*cos(v),u*sin(v),v)", 161 | "", 162 | 163 | "abs(cross(d(P,u),d(P,v)))", 164 | "(1+u^2)^(1/2)", 165 | }; 166 | 167 | void 168 | test_abs(void) 169 | { 170 | test(__FILE__, s, sizeof s / sizeof (char *)); 171 | } 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /Eigenmath/Sources/adj.cpp: -------------------------------------------------------------------------------- 1 | // Adjunct of a matrix 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_adj(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | adj(); 11 | } 12 | 13 | void 14 | adj(void) 15 | { 16 | int i, j, n; 17 | 18 | save(); 19 | 20 | p1 = pop(); 21 | 22 | if (istensor(p1) && p1->u.tensor->ndim == 2 && p1->u.tensor->dim[0] == p1->u.tensor->dim[1]); 23 | else 24 | stop("adj: square matrix expected"); 25 | 26 | n = p1->u.tensor->dim[0]; 27 | 28 | p2 = alloc_tensor(n * n); 29 | 30 | p2->u.tensor->ndim = 2; 31 | p2->u.tensor->dim[0] = n; 32 | p2->u.tensor->dim[1] = n; 33 | 34 | for (i = 0; i < n; i++) 35 | for (j = 0; j < n; j++) 36 | { 37 | cofactor(p1, n, i, j); 38 | p2->u.tensor->elem[n * j + i] = pop(); /* transpose */ 39 | } 40 | 41 | push(p2); 42 | 43 | restore(); 44 | } 45 | 46 | #if SELFTEST 47 | 48 | static char *s[] = { 49 | 50 | "adj(((a,b),(c,d)))", 51 | "((d,-b),(-c,a))", 52 | 53 | "adj(((1,2),(3,4)))", 54 | "((4,-2),(-3,1))", 55 | 56 | "adj(((2,3,-2,5),(6,-2,1,4),(5,10,3,-2),(-1,2,2,3)))", 57 | "((-4,-177,-73,194),(-117,117,-99,-27),(310,-129,-44,-374),(-130,-51,71,-211))", 58 | }; 59 | 60 | void 61 | test_adj(void) 62 | { 63 | test(__FILE__, s, sizeof s / sizeof (char *)); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Eigenmath/Sources/alloc.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | U *mem[M]; 5 | int mcount; 6 | 7 | U *free_list; 8 | int free_count; 9 | 10 | U * 11 | alloc(void) 12 | { 13 | U *p; 14 | if (free_count == 0) 15 | { 16 | if (mcount == 0) 17 | alloc_mem(); 18 | else 19 | { 20 | gc(); 21 | if (free_count < N * mcount / 2) 22 | alloc_mem(); 23 | } 24 | if (free_count == 0) 25 | stop("atom space exhausted"); 26 | } 27 | p = free_list; 28 | free_list = free_list->u.cons.cdr; 29 | free_count--; 30 | return p; 31 | } 32 | 33 | U * 34 | alloc_tensor(int nelem) 35 | { 36 | int i; 37 | U *p; 38 | p = alloc(); 39 | p->k = TENSOR; 40 | p->u.tensor = (T *)malloc(sizeof(T) + nelem * sizeof(U *)); 41 | if (p->u.tensor == NULL) 42 | out_of_memory(); 43 | p->u.tensor->nelem = nelem; 44 | for (i = 0; i < nelem; i++) 45 | p->u.tensor->elem[i] = zero; 46 | return p; 47 | } 48 | 49 | // garbage collector 50 | 51 | void 52 | gc(void) 53 | { 54 | int i, j; 55 | U *p; 56 | 57 | // tag everything 58 | 59 | for (i = 0; i < mcount; i++) 60 | { 61 | p = mem[i]; 62 | for (j = 0; j < N; j++) 63 | p[j].tag = 1; 64 | } 65 | 66 | // untag what's used 67 | 68 | untag(p0); 69 | untag(p1); 70 | untag(p2); 71 | untag(p3); 72 | untag(p4); 73 | untag(p5); 74 | untag(p6); 75 | untag(p7); 76 | untag(p8); 77 | untag(p9); 78 | 79 | untag(one); 80 | untag(zero); 81 | untag(imaginaryunit); 82 | 83 | for (i = 0; i < NSYM; i++) 84 | { 85 | untag(binding[i]); 86 | untag(arglist[i]); 87 | } 88 | 89 | for (i = 0; i < tos; i++) 90 | untag(stack[i]); 91 | 92 | for (i = (int)(frame - stack); i < TOS; i++) 93 | untag(stack[i]); 94 | 95 | // collect everything that's still tagged 96 | 97 | free_count = 0; 98 | 99 | for (i = 0; i < mcount; i++) 100 | { 101 | p = mem[i]; 102 | for (j = 0; j < N; j++) 103 | { 104 | if (p[j].tag == 0) 105 | continue; 106 | // still tagged so it's unused, put on free list 107 | switch (p[j].k) 108 | { 109 | case TENSOR: 110 | free(p[j].u.tensor); 111 | break; 112 | case STR: 113 | free(p[j].u.str); 114 | break; 115 | case NUM: 116 | mfree(p[j].u.q.a); 117 | mfree(p[j].u.q.b); 118 | break; 119 | } 120 | p[j].k = CONS; // so no double free occurs above 121 | p[j].u.cons.cdr = free_list; 122 | free_list = p + j; 123 | free_count++; 124 | } 125 | } 126 | } 127 | 128 | void 129 | untag(U *p) 130 | { 131 | int i; 132 | 133 | if (iscons(p)) 134 | { 135 | do 136 | { 137 | if (p->tag == 0) 138 | return; 139 | p->tag = 0; 140 | untag(p->u.cons.car); 141 | p = p->u.cons.cdr; 142 | } 143 | while (iscons(p)); 144 | untag(p); 145 | return; 146 | } 147 | 148 | if (p->tag) 149 | { 150 | p->tag = 0; 151 | if (istensor(p)) 152 | { 153 | for (i = 0; i < p->u.tensor->nelem; i++) 154 | untag(p->u.tensor->elem[i]); 155 | } 156 | } 157 | } 158 | 159 | // get memory for 100,000 atoms 160 | 161 | void 162 | alloc_mem(void) 163 | { 164 | int i; 165 | U *p; 166 | if (mcount == M) 167 | return; 168 | p = (U *)malloc(N * sizeof(struct U)); 169 | if (p == NULL) 170 | return; 171 | mem[mcount++] = p; 172 | for (i = 0; i < N; i++) 173 | { 174 | p[i].k = CONS; // so no free in gc 175 | p[i].u.cons.cdr = p + i + 1; 176 | } 177 | p[N - 1].u.cons.cdr = free_list; 178 | free_list = p; 179 | free_count += N; 180 | } 181 | 182 | void 183 | print_mem_info(void) 184 | { 185 | char buf[100]; 186 | 187 | sprintf(buf, "%d blocks (%d bytes/block)\n", N * mcount, (int)sizeof(U)); 188 | printstr(buf); 189 | 190 | sprintf(buf, "%d free\n", free_count); 191 | printstr(buf); 192 | 193 | sprintf(buf, "%d used\n", N * mcount - free_count); 194 | printstr(buf); 195 | } 196 | -------------------------------------------------------------------------------- /Eigenmath/Sources/append.cpp: -------------------------------------------------------------------------------- 1 | // Append one list to another. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | append(void) 7 | { 8 | int h; 9 | 10 | save(); 11 | 12 | p2 = pop(); 13 | p1 = pop(); 14 | 15 | h = tos; 16 | 17 | while (iscons(p1)) 18 | { 19 | push(car(p1)); 20 | p1 = cdr(p1); 21 | } 22 | 23 | while (iscons(p2)) 24 | { 25 | push(car(p2)); 26 | p2 = cdr(p2); 27 | } 28 | 29 | list(tos - h); 30 | 31 | restore(); 32 | } 33 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arccos.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arccos(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arccos(); 10 | } 11 | 12 | void 13 | arccos(void) 14 | { 15 | int n; 16 | double d; 17 | 18 | save(); 19 | 20 | p1 = pop(); 21 | 22 | if (car(p1) == symbol(COS)) 23 | { 24 | push(cadr(p1)); 25 | restore(); 26 | return; 27 | } 28 | 29 | if (isdouble(p1)) 30 | { 31 | errno = 0; 32 | d = acos(p1->u.d); 33 | if (errno) 34 | stop("arccos function argument is not in the interval [-1,1]"); 35 | push_double(d); 36 | restore(); 37 | return; 38 | } 39 | 40 | // if p1 == 1/sqrt(2) then return 1/4*pi (45 degrees) 41 | 42 | if (isoneoversqrttwo(p1)) 43 | { 44 | push_rational(1, 4); 45 | push_symbol(PI); 46 | multiply(); 47 | restore(); 48 | return; 49 | } 50 | 51 | // if p1 == -1/sqrt(2) then return 3/4*pi (135 degrees) 52 | 53 | if (isminusoneoversqrttwo(p1)) 54 | { 55 | push_rational(3, 4); 56 | push_symbol(PI); 57 | multiply(); 58 | restore(); 59 | return; 60 | } 61 | 62 | if (!isrational(p1)) 63 | { 64 | push_symbol(ARCCOS); 65 | push(p1); 66 | list(2); 67 | restore(); 68 | return; 69 | } 70 | 71 | push(p1); 72 | push_integer(2); 73 | multiply(); 74 | n = pop_integer(); 75 | 76 | switch (n) 77 | { 78 | 79 | case -2: 80 | push_symbol(PI); 81 | break; 82 | 83 | case -1: 84 | push_rational(2, 3); 85 | push_symbol(PI); 86 | multiply(); 87 | break; 88 | 89 | case 0: 90 | push_rational(1, 2); 91 | push_symbol(PI); 92 | multiply(); 93 | break; 94 | 95 | case 1: 96 | push_rational(1, 3); 97 | push_symbol(PI); 98 | multiply(); 99 | break; 100 | 101 | case 2: 102 | push(zero); 103 | break; 104 | 105 | default: 106 | push_symbol(ARCCOS); 107 | push(p1); 108 | list(2); 109 | break; 110 | } 111 | 112 | restore(); 113 | } 114 | 115 | #if SELFTEST 116 | 117 | static char *s[] = { 118 | 119 | "arccos(1)", 120 | "0", 121 | 122 | "arccos(1/2)", 123 | "1/3*pi", 124 | 125 | "arccos(0)", 126 | "1/2*pi", 127 | 128 | "arccos(-1/2)", 129 | "2/3*pi", 130 | 131 | "arccos(-1)", 132 | "pi", 133 | 134 | "arccos(cos(0))", 135 | "0", 136 | 137 | "arccos(cos(1/3*pi))", 138 | "1/3*pi", 139 | 140 | "arccos(cos(1/2*pi))", 141 | "1/2*pi", 142 | 143 | "arccos(cos(2/3*pi))", 144 | "2/3*pi", 145 | 146 | "arccos(cos(pi))", 147 | "pi", 148 | 149 | "arccos(cos(x))", 150 | "x", 151 | 152 | "arccos(1/sqrt(2))", 153 | "1/4*pi", 154 | 155 | "arccos(-1/sqrt(2))", 156 | "3/4*pi", 157 | 158 | "arccos(cos(1/4*pi))", 159 | "1/4*pi", 160 | 161 | "arccos(cos(3/4*pi))", 162 | "3/4*pi", 163 | }; 164 | 165 | void 166 | test_arccos(void) 167 | { 168 | test(__FILE__, s, sizeof s / sizeof (char *)); 169 | } 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arccosh.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arccosh(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arccosh(); 10 | } 11 | 12 | void 13 | arccosh(void) 14 | { 15 | double d; 16 | save(); 17 | p1 = pop(); 18 | if (car(p1) == symbol(COSH)) 19 | { 20 | push(cadr(p1)); 21 | restore(); 22 | return; 23 | } 24 | if (isdouble(p1)) 25 | { 26 | d = p1->u.d; 27 | if (d < 1.0) 28 | stop("arccosh function argument is less than 1.0"); 29 | d = log(d + sqrt(d * d - 1.0)); 30 | push_double(d); 31 | restore(); 32 | return; 33 | } 34 | if (isplusone(p1)) 35 | { 36 | push(zero); 37 | restore(); 38 | return; 39 | } 40 | push_symbol(ARCCOSH); 41 | push(p1); 42 | list(2); 43 | restore(); 44 | } 45 | 46 | #if SELFTEST 47 | 48 | static char *s[] = { 49 | 50 | "arccosh(1.0)", 51 | "0", 52 | 53 | "arccosh(1)", 54 | "0", 55 | 56 | "arccosh(cosh(x))", 57 | "x", 58 | }; 59 | 60 | void 61 | test_arccosh(void) 62 | { 63 | test(__FILE__, s, sizeof s / sizeof (char *)); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arcsin.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arcsin(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arcsin(); 10 | } 11 | 12 | void 13 | arcsin(void) 14 | { 15 | int n; 16 | double d; 17 | 18 | save(); 19 | 20 | p1 = pop(); 21 | 22 | if (car(p1) == symbol(SIN)) 23 | { 24 | push(cadr(p1)); 25 | restore(); 26 | return; 27 | } 28 | 29 | if (isdouble(p1)) 30 | { 31 | errno = 0; 32 | d = asin(p1->u.d); 33 | if (errno) 34 | stop("arcsin function argument is not in the interval [-1,1]"); 35 | push_double(d); 36 | restore(); 37 | return; 38 | } 39 | 40 | // if p1 == 1/sqrt(2) then return 1/4*pi (45 degrees) 41 | 42 | if (isoneoversqrttwo(p1)) 43 | { 44 | push_rational(1, 4); 45 | push_symbol(PI); 46 | multiply(); 47 | restore(); 48 | return; 49 | } 50 | 51 | // if p1 == -1/sqrt(2) then return -1/4*pi (-45 degrees) 52 | 53 | if (isminusoneoversqrttwo(p1)) 54 | { 55 | push_rational(-1, 4); 56 | push_symbol(PI); 57 | multiply(); 58 | restore(); 59 | return; 60 | } 61 | 62 | if (!isrational(p1)) 63 | { 64 | push_symbol(ARCSIN); 65 | push(p1); 66 | list(2); 67 | restore(); 68 | return; 69 | } 70 | 71 | push(p1); 72 | push_integer(2); 73 | multiply(); 74 | n = pop_integer(); 75 | 76 | switch (n) 77 | { 78 | 79 | case -2: 80 | push_rational(-1, 2); 81 | push_symbol(PI); 82 | multiply(); 83 | break; 84 | 85 | case -1: 86 | push_rational(-1, 6); 87 | push_symbol(PI); 88 | multiply(); 89 | break; 90 | 91 | case 0: 92 | push(zero); 93 | break; 94 | 95 | case 1: 96 | push_rational(1, 6); 97 | push_symbol(PI); 98 | multiply(); 99 | break; 100 | 101 | case 2: 102 | push_rational(1, 2); 103 | push_symbol(PI); 104 | multiply(); 105 | break; 106 | 107 | default: 108 | push_symbol(ARCSIN); 109 | push(p1); 110 | list(2); 111 | break; 112 | } 113 | 114 | restore(); 115 | } 116 | 117 | #if SELFTEST 118 | 119 | static char *s[] = { 120 | 121 | "arcsin(-1)", 122 | "-1/2*pi", 123 | 124 | "arcsin(-1/2)", 125 | "-1/6*pi", 126 | 127 | "arcsin(0)", 128 | "0", 129 | 130 | "arcsin(1/2)", 131 | "1/6*pi", 132 | 133 | "arcsin(1)", 134 | "1/2*pi", 135 | 136 | "arcsin(sin(-1/2*pi))", 137 | "-1/2*pi", 138 | 139 | "arcsin(sin(-1/6*pi))", 140 | "-1/6*pi", 141 | 142 | "arcsin(sin(0))", 143 | "0", 144 | 145 | "arcsin(sin(1/6*pi))", 146 | "1/6*pi", 147 | 148 | "arcsin(sin(1/2*pi))", 149 | "1/2*pi", 150 | 151 | "arcsin(sin(x))", 152 | "x", 153 | 154 | "arcsin(1/sqrt(2))", 155 | "1/4*pi", 156 | 157 | "arcsin(-1/sqrt(2))", 158 | "-1/4*pi", 159 | 160 | "arcsin(sin(1/4*pi))", 161 | "1/4*pi", 162 | 163 | "arcsin(sin(-1/4*pi))", 164 | "-1/4*pi", 165 | }; 166 | 167 | void 168 | test_arcsin(void) 169 | { 170 | test(__FILE__, s, sizeof s / sizeof (char *)); 171 | } 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arcsinh.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arcsinh(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arcsinh(); 10 | } 11 | 12 | void 13 | arcsinh(void) 14 | { 15 | double d; 16 | save(); 17 | p1 = pop(); 18 | if (car(p1) == symbol(SINH)) 19 | { 20 | push(cadr(p1)); 21 | restore(); 22 | return; 23 | } 24 | if (isdouble(p1)) 25 | { 26 | d = p1->u.d; 27 | d = log(d + sqrt(d * d + 1.0)); 28 | push_double(d); 29 | restore(); 30 | return; 31 | } 32 | if (iszero(p1)) 33 | { 34 | push(zero); 35 | restore(); 36 | return; 37 | } 38 | push_symbol(ARCSINH); 39 | push(p1); 40 | list(2); 41 | restore(); 42 | } 43 | 44 | #if SELFTEST 45 | 46 | static char *s[] = { 47 | 48 | "arcsinh(0.0)", 49 | "0", 50 | 51 | "arcsinh(0)", 52 | "0", 53 | 54 | "arcsinh(sinh(x))", 55 | "x", 56 | }; 57 | 58 | void 59 | test_arcsinh(void) 60 | { 61 | test(__FILE__, s, sizeof s / sizeof (char *)); 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arctan.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arctan(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arctan(); 10 | } 11 | 12 | void 13 | arctan(void) 14 | { 15 | double d; 16 | 17 | save(); 18 | 19 | p1 = pop(); 20 | 21 | if (car(p1) == symbol(TAN)) 22 | { 23 | push(cadr(p1)); 24 | restore(); 25 | return; 26 | } 27 | 28 | if (isdouble(p1)) 29 | { 30 | errno = 0; 31 | d = atan(p1->u.d); 32 | if (errno) 33 | stop("arctan function error"); 34 | push_double(d); 35 | restore(); 36 | return; 37 | } 38 | 39 | if (iszero(p1)) 40 | { 41 | push(zero); 42 | restore(); 43 | return; 44 | } 45 | 46 | if (isnegative(p1)) 47 | { 48 | push(p1); 49 | negate(); 50 | arctan(); 51 | negate(); 52 | restore(); 53 | return; 54 | } 55 | 56 | // arctan(sin(a) / cos(a)) ? 57 | 58 | if (find(p1, symbol(SIN)) && find(p1, symbol(COS))) 59 | { 60 | push(p1); 61 | numerator(); 62 | p2 = pop(); 63 | push(p1); 64 | denominator(); 65 | p3 = pop(); 66 | if (car(p2) == symbol(SIN) && car(p3) == symbol(COS) && equal(cadr(p2), cadr(p3))) 67 | { 68 | push(cadr(p2)); 69 | restore(); 70 | return; 71 | } 72 | } 73 | 74 | // arctan(1/sqrt(3)) -> pi/6 75 | 76 | if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), -1, 2)) 77 | { 78 | push_rational(1, 6); 79 | push(symbol(PI)); 80 | multiply(); 81 | restore(); 82 | return; 83 | } 84 | 85 | // arctan(1) -> pi/4 86 | 87 | if (equaln(p1, 1)) 88 | { 89 | push_rational(1, 4); 90 | push(symbol(PI)); 91 | multiply(); 92 | restore(); 93 | return; 94 | } 95 | 96 | // arctan(sqrt(3)) -> pi/3 97 | 98 | if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), 1, 2)) 99 | { 100 | push_rational(1, 3); 101 | push(symbol(PI)); 102 | multiply(); 103 | restore(); 104 | return; 105 | } 106 | 107 | push_symbol(ARCTAN); 108 | push(p1); 109 | list(2); 110 | 111 | restore(); 112 | } 113 | 114 | #if SELFTEST 115 | 116 | static char *s[] = { 117 | 118 | "arctan(x)", 119 | "arctan(x)", 120 | 121 | "arctan(-x)", 122 | "-arctan(x)", 123 | 124 | "arctan(0)", 125 | "0", 126 | 127 | "arctan(tan(x))", 128 | "x", 129 | 130 | "arctan(1/sqrt(3))-pi/6", // 30 degrees 131 | "0", 132 | 133 | "arctan(1)-pi/4", // 45 degrees 134 | "0", 135 | 136 | "arctan(sqrt(3))-pi/3", // 60 degrees 137 | "0", 138 | 139 | "arctan(a-b)", 140 | "arctan(a-b)", 141 | 142 | "arctan(b-a)", 143 | "-arctan(a-b)", 144 | 145 | "arctan(tan(x))", 146 | "x", 147 | }; 148 | 149 | void 150 | test_arctan(void) 151 | { 152 | test(__FILE__, s, sizeof s / sizeof (char *)); 153 | } 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arctanh.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_arctanh(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | arctanh(); 10 | } 11 | 12 | void 13 | arctanh(void) 14 | { 15 | double d; 16 | save(); 17 | p1 = pop(); 18 | if (car(p1) == symbol(TANH)) 19 | { 20 | push(cadr(p1)); 21 | restore(); 22 | return; 23 | } 24 | if (isdouble(p1)) 25 | { 26 | d = p1->u.d; 27 | if (d < -1.0 || d > 1.0) 28 | stop("arctanh function argument is not in the interval [-1,1]"); 29 | d = log((1.0 + d) / (1.0 - d)) / 2.0; 30 | push_double(d); 31 | restore(); 32 | return; 33 | } 34 | if (iszero(p1)) 35 | { 36 | push(zero); 37 | restore(); 38 | return; 39 | } 40 | push_symbol(ARCTANH); 41 | push(p1); 42 | list(2); 43 | restore(); 44 | } 45 | 46 | #if SELFTEST 47 | 48 | static char *s[] = { 49 | 50 | "arctanh(0.0)", 51 | "0", 52 | 53 | "arctanh(0)", 54 | "0", 55 | 56 | "arctanh(tanh(x))", 57 | "x", 58 | }; 59 | 60 | void 61 | test_arctanh(void) 62 | { 63 | test(__FILE__, s, sizeof s / sizeof (char *)); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Eigenmath/Sources/arg.cpp: -------------------------------------------------------------------------------- 1 | /* Argument (angle) of complex z 2 | 3 | z arg(z) 4 | - ------ 5 | 6 | a 0 7 | 8 | -a -pi See note 3 below 9 | 10 | (-1)^a a pi 11 | 12 | exp(a + i b) b 13 | 14 | a b arg(a) + arg(b) 15 | 16 | a + i b arctan(b/a) 17 | 18 | Result by quadrant 19 | 20 | z arg(z) 21 | - ------ 22 | 23 | 1 + i 1/4 pi 24 | 25 | 1 - i -1/4 pi 26 | 27 | -1 + i 3/4 pi 28 | 29 | -1 - i -3/4 pi 30 | 31 | Notes 32 | 33 | 1. Handles mixed polar and rectangular forms, e.g. 1 + exp(i pi/3) 34 | 35 | 2. Symbols in z are assumed to be positive and real. 36 | 37 | 3. Negative direction adds -pi to angle. 38 | 39 | Example: z = (-1)^(1/3), mag(z) = 1/3 pi, mag(-z) = -2/3 pi 40 | 41 | 4. jean-francois.debroux reports that when z=(a+i*b)/(c+i*d) then 42 | 43 | arg(numerator(z)) - arg(denominator(z)) 44 | 45 | must be used to get the correct answer. Now the operation is 46 | automatic. 47 | */ 48 | 49 | #include "../Headers/defs.h" 50 | 51 | void 52 | eval_arg(void) 53 | { 54 | push(cadr(p1)); 55 | eval(); 56 | arg(); 57 | } 58 | 59 | void 60 | arg(void) 61 | { 62 | save(); 63 | p1 = pop(); 64 | push(p1); 65 | numerator(); 66 | yyarg(); 67 | push(p1); 68 | denominator(); 69 | yyarg(); 70 | subtract(); 71 | restore(); 72 | } 73 | 74 | #define RE p2 75 | #define IM p3 76 | 77 | void 78 | yyarg(void) 79 | { 80 | save(); 81 | p1 = pop(); 82 | if (isnegativenumber(p1)) 83 | { 84 | push(symbol(PI)); 85 | negate(); 86 | } 87 | else if (car(p1) == symbol(POWER) && equaln(cadr(p1), -1)) 88 | { 89 | // -1 to a power 90 | push(symbol(PI)); 91 | push(caddr(p1)); 92 | multiply(); 93 | } 94 | else if (car(p1) == symbol(POWER) && cadr(p1) == symbol(E)) 95 | { 96 | // exponential 97 | push(caddr(p1)); 98 | imag(); 99 | } 100 | else if (car(p1) == symbol(MULTIPLY)) 101 | { 102 | // product of factors 103 | push_integer(0); 104 | p1 = cdr(p1); 105 | while (iscons(p1)) 106 | { 107 | push(car(p1)); 108 | arg(); 109 | add(); 110 | p1 = cdr(p1); 111 | } 112 | } 113 | else if (car(p1) == symbol(ADD)) 114 | { 115 | // sum of terms 116 | push(p1); 117 | rect(); 118 | p1 = pop(); 119 | push(p1); 120 | real(); 121 | RE = pop(); 122 | push(p1); 123 | imag(); 124 | IM = pop(); 125 | if (iszero(RE)) 126 | { 127 | push(symbol(PI)); 128 | if (isnegative(IM)) 129 | negate(); 130 | } 131 | else 132 | { 133 | push(IM); 134 | push(RE); 135 | divide(); 136 | arctan(); 137 | if (isnegative(RE)) 138 | { 139 | push_symbol(PI); 140 | if (isnegative(IM)) 141 | subtract(); // quadrant 1 -> 3 142 | else 143 | add(); // quadrant 4 -> 2 144 | } 145 | } 146 | } 147 | else 148 | // pure real 149 | push_integer(0); 150 | restore(); 151 | } 152 | 153 | #if SELFTEST 154 | 155 | static char *s[] = { 156 | 157 | "arg(1+i)", 158 | "1/4*pi", 159 | 160 | "arg(1-i)", 161 | "-1/4*pi", 162 | 163 | "arg(-1+i)", 164 | "3/4*pi", 165 | 166 | "arg(-1-i)", 167 | "-3/4*pi", 168 | 169 | "arg((-1)^(1/3))", 170 | "1/3*pi", 171 | 172 | "arg(1+exp(i*pi/3))", 173 | "1/6*pi", 174 | 175 | "arg((-1)^(1/6)*exp(i*pi/6))", 176 | "1/3*pi", 177 | 178 | "arg(a)", 179 | "0", 180 | 181 | "arg(a*exp(b+i*pi/5))", 182 | "1/5*pi", 183 | 184 | "arg(-1)", 185 | "-pi", 186 | 187 | "arg(a)", 188 | "0", 189 | 190 | "arg(-a)", 191 | "-pi", 192 | 193 | "arg(-(-1)^(1/3))", 194 | "-2/3*pi", 195 | 196 | "arg(-exp(i*pi/3))", 197 | "-2/3*pi", 198 | 199 | "arg(-i)", 200 | "-1/2*pi", 201 | 202 | "arg((a+b*i)/(c+d*i))", 203 | "arctan(b/a)-arctan(d/c)", 204 | }; 205 | 206 | void 207 | test_arg(void) 208 | { 209 | test(__FILE__, s, sizeof s / sizeof (char *)); 210 | } 211 | 212 | #endif 213 | -------------------------------------------------------------------------------- /Eigenmath/Sources/atomize.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_atomize(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | p1 = pop(); 10 | if (iscons(p1)) 11 | atomize(); 12 | else 13 | push(p1); 14 | } 15 | 16 | void 17 | atomize(void) 18 | { 19 | int i, n; 20 | p1 = cdr(p1); 21 | n = length(p1); 22 | if (n == 1) 23 | { 24 | push(car(p1)); 25 | return; 26 | } 27 | p2 = alloc_tensor(n); 28 | p2->u.tensor->ndim = 1; 29 | p2->u.tensor->dim[0] = n; 30 | for (i = 0; i < n; i++) 31 | { 32 | p2->u.tensor->elem[i] = car(p1); 33 | p1 = cdr(p1); 34 | } 35 | push(p2); 36 | } 37 | -------------------------------------------------------------------------------- /Eigenmath/Sources/bake.cpp: -------------------------------------------------------------------------------- 1 | // pretty print 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | bake(void) 7 | { 8 | int h, s, t, x, y, z; 9 | 10 | expanding++; 11 | 12 | save(); 13 | 14 | p1 = pop(); 15 | 16 | s = ispoly(p1, symbol(SYMBOL_S)); 17 | t = ispoly(p1, symbol(SYMBOL_T)); 18 | x = ispoly(p1, symbol(SYMBOL_X)); 19 | y = ispoly(p1, symbol(SYMBOL_Y)); 20 | z = ispoly(p1, symbol(SYMBOL_Z)); 21 | 22 | if (s == 1 && t == 0 && x == 0 && y == 0 && z == 0) 23 | { 24 | p2 = symbol(SYMBOL_S); 25 | bake_poly(); 26 | } 27 | else if (s == 0 && t == 1 && x == 0 && y == 0 && z == 0) 28 | { 29 | p2 = symbol(SYMBOL_T); 30 | bake_poly(); 31 | } 32 | else if (s == 0 && t == 0 && x == 1 && y == 0 && z == 0) 33 | { 34 | p2 = symbol(SYMBOL_X); 35 | bake_poly(); 36 | } 37 | else if (s == 0 && t == 0 && x == 0 && y == 1 && z == 0) 38 | { 39 | p2 = symbol(SYMBOL_Y); 40 | bake_poly(); 41 | } 42 | else if (s == 0 && t == 0 && x == 0 && y == 0 && z == 1) 43 | { 44 | p2 = symbol(SYMBOL_Z); 45 | bake_poly(); 46 | } 47 | else if (iscons(p1)) 48 | { 49 | h = tos; 50 | push(car(p1)); 51 | p1 = cdr(p1); 52 | while (iscons(p1)) 53 | { 54 | push(car(p1)); 55 | bake(); 56 | p1 = cdr(p1); 57 | } 58 | list(tos - h); 59 | } 60 | else 61 | push(p1); 62 | 63 | restore(); 64 | 65 | expanding--; 66 | } 67 | 68 | void 69 | polyform(void) 70 | { 71 | int h; 72 | 73 | save(); 74 | 75 | p2 = pop(); 76 | p1 = pop(); 77 | 78 | if (ispoly(p1, p2)) 79 | bake_poly(); 80 | else if (iscons(p1)) 81 | { 82 | h = tos; 83 | push(car(p1)); 84 | p1 = cdr(p1); 85 | while (iscons(p1)) 86 | { 87 | push(car(p1)); 88 | push(p2); 89 | polyform(); 90 | p1 = cdr(p1); 91 | } 92 | list(tos - h); 93 | } 94 | else 95 | push(p1); 96 | 97 | restore(); 98 | } 99 | 100 | void 101 | bake_poly() 102 | { 103 | int h, i, k, n; 104 | U **a; 105 | a = stack + tos; 106 | push(p1); // p(x) 107 | push(p2); // x 108 | k = coeff(); 109 | h = tos; 110 | for (i = k - 1; i >= 0; i--) 111 | { 112 | p1 = a[i]; 113 | bake_poly_term(i); 114 | } 115 | n = tos - h; 116 | if (n > 1) 117 | { 118 | list(n); 119 | push(symbol(ADD)); 120 | swap(); 121 | cons(); 122 | } 123 | p1 = pop(); 124 | tos -= k; 125 | push(p1); 126 | } 127 | 128 | // p1 points to coefficient of p2 ^ k 129 | 130 | void 131 | bake_poly_term(int k) 132 | { 133 | int h, n; 134 | 135 | if (iszero(p1)) 136 | return; 137 | 138 | // constant term? 139 | 140 | if (k == 0) 141 | { 142 | if (car(p1) == symbol(ADD)) 143 | { 144 | p1 = cdr(p1); 145 | while (iscons(p1)) 146 | { 147 | push(car(p1)); 148 | p1 = cdr(p1); 149 | } 150 | } 151 | else 152 | push(p1); 153 | return; 154 | } 155 | 156 | h = tos; 157 | 158 | // coefficient 159 | 160 | if (car(p1) == symbol(MULTIPLY)) 161 | { 162 | p1 = cdr(p1); 163 | while (iscons(p1)) 164 | { 165 | push(car(p1)); 166 | p1 = cdr(p1); 167 | } 168 | } 169 | else if (!equaln(p1, 1)) 170 | push(p1); 171 | 172 | // x ^ k 173 | 174 | if (k == 1) 175 | push(p2); 176 | else 177 | { 178 | push(symbol(POWER)); 179 | push(p2); 180 | push_integer(k); 181 | list(3); 182 | } 183 | 184 | n = tos - h; 185 | 186 | if (n > 1) 187 | { 188 | list(n); 189 | push(symbol(MULTIPLY)); 190 | swap(); 191 | cons(); 192 | } 193 | } 194 | 195 | #if SELFTEST 196 | 197 | static char *s[] = { 198 | 199 | "(x+3)^3", 200 | "x^3+9*x^2+27*x+27", 201 | 202 | "factor", 203 | "(x+3)^3", 204 | }; 205 | 206 | void 207 | test_bake(void) 208 | { 209 | test(__FILE__, s, sizeof s / sizeof (char *)); 210 | } 211 | 212 | #endif 213 | -------------------------------------------------------------------------------- /Eigenmath/Sources/bessely.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Bessel Y function 4 | // 5 | // Input: tos-2 x (can be a symbol or expr) 6 | // 7 | // tos-1 n 8 | // 9 | // Output: Result on stack 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "../Headers/defs.h" 14 | 15 | void 16 | eval_bessely(void) 17 | { 18 | push(cadr(p1)); 19 | eval(); 20 | push(caddr(p1)); 21 | eval(); 22 | bessely(); 23 | } 24 | 25 | void 26 | bessely(void) 27 | { 28 | save(); 29 | yybessely(); 30 | restore(); 31 | } 32 | 33 | #define X p1 34 | #define N p2 35 | 36 | void 37 | yybessely(void) 38 | { 39 | double d; 40 | int n; 41 | 42 | N = pop(); 43 | X = pop(); 44 | 45 | push(N); 46 | n = pop_integer(); 47 | 48 | if (isdouble(X) && n != (int)0x80000000) 49 | { 50 | d = yn(n, X->u.d); 51 | push_double(d); 52 | return; 53 | } 54 | 55 | if (isnegativeterm(N)) 56 | { 57 | push_integer(-1); 58 | push(N); 59 | power(); 60 | push_symbol(BESSELY); 61 | push(X); 62 | push(N); 63 | negate(); 64 | list(3); 65 | multiply(); 66 | return; 67 | } 68 | 69 | push_symbol(BESSELY); 70 | push(X); 71 | push(N); 72 | list(3); 73 | return; 74 | } 75 | 76 | #if SELFTEST 77 | 78 | static char *s[] = { 79 | 80 | "bessely(x,n)", 81 | "bessely(x,n)", 82 | }; 83 | 84 | void 85 | test_bessely(void) 86 | { 87 | test(__FILE__, s, sizeof s / sizeof (char *)); 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /Eigenmath/Sources/binomial.cpp: -------------------------------------------------------------------------------- 1 | // Binomial coefficient 2 | // 3 | // Input: tos-2 n 4 | // 5 | // tos-1 k 6 | // 7 | // Output: Binomial coefficient on stack 8 | // 9 | // binomial(n, k) = n! / k! / (n - k)! 10 | // 11 | // The binomial coefficient vanishes for k < 0 or k > n. (A=B, p. 19) 12 | 13 | #include "../Headers/defs.h" 14 | 15 | static void ybinomial(void); 16 | static int check_args(void); 17 | 18 | void 19 | eval_binomial(void) 20 | { 21 | push(cadr(p1)); 22 | eval(); 23 | push(caddr(p1)); 24 | eval(); 25 | binomial(); 26 | } 27 | 28 | void 29 | binomial(void) 30 | { 31 | save(); 32 | ybinomial(); 33 | restore(); 34 | } 35 | 36 | #define N p1 37 | #define K p2 38 | 39 | static void 40 | ybinomial(void) 41 | { 42 | K = pop(); 43 | N = pop(); 44 | 45 | if (check_args() == 0) 46 | { 47 | push(zero); 48 | return; 49 | } 50 | 51 | push(N); 52 | factorial(); 53 | 54 | push(K); 55 | factorial(); 56 | 57 | divide(); 58 | 59 | push(N); 60 | push(K); 61 | subtract(); 62 | factorial(); 63 | 64 | divide(); 65 | } 66 | 67 | static int 68 | check_args(void) 69 | { 70 | if (isnum(N) && lessp(N, zero)) 71 | return 0; 72 | else if (isnum(K) && lessp(K, zero)) 73 | return 0; 74 | else if (isnum(N) && isnum(K) && lessp(N, K)) 75 | return 0; 76 | else 77 | return 1; 78 | } 79 | 80 | #if SELFTEST 81 | 82 | char *s[] = { 83 | 84 | "binomial(12,6)", 85 | "924", 86 | 87 | "binomial(n,k)", 88 | // "1/(factorial(k))*factorial(n)*1/(factorial(-k+n))", 89 | // "factorial(n)/(factorial(k)*factorial(-k+n))", 90 | "n!/(k!*(-k+n)!)", 91 | 92 | "binomial(0,k)", 93 | // "1/(factorial(k))*1/(factorial(-k))", 94 | // "1/(factorial(k)*factorial(-k))", 95 | "1/(k!*(-k)!)", 96 | 97 | "binomial(n,0)", 98 | "1", 99 | 100 | "binomial(-1,k)", 101 | "0", 102 | 103 | "binomial(n,-1)", 104 | "0", 105 | }; 106 | 107 | void 108 | test_binomial(void) 109 | { 110 | test(__FILE__, s, sizeof s / sizeof (char *)); 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /Eigenmath/Sources/ceiling.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_ceiling(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | ceiling(); 10 | } 11 | 12 | void 13 | ceiling(void) 14 | { 15 | save(); 16 | yyceiling(); 17 | restore(); 18 | } 19 | 20 | void 21 | yyceiling(void) 22 | { 23 | double d; 24 | 25 | p1 = pop(); 26 | 27 | if (!isnum(p1)) 28 | { 29 | push_symbol(CEILING); 30 | push(p1); 31 | list(2); 32 | return; 33 | } 34 | 35 | if (isdouble(p1)) 36 | { 37 | d = ceil(p1->u.d); 38 | push_double(d); 39 | return; 40 | } 41 | 42 | if (isinteger(p1)) 43 | { 44 | push(p1); 45 | return; 46 | } 47 | 48 | p3 = alloc(); 49 | p3->k = NUM; 50 | p3->u.q.a = mdiv(p1->u.q.a, p1->u.q.b); 51 | p3->u.q.b = mint(1); 52 | push(p3); 53 | 54 | if (isnegativenumber(p1)); 55 | else 56 | { 57 | push_integer(1); 58 | add(); 59 | } 60 | } 61 | 62 | #if SELFTEST 63 | 64 | static char *s[] = { 65 | 66 | "ceiling(a)", 67 | "ceiling(a)", 68 | 69 | "ceiling(a+b)", 70 | "ceiling(a+b)", 71 | 72 | "ceiling(5/2)", 73 | "3", 74 | 75 | "ceiling(4/2)", 76 | "2", 77 | 78 | "ceiling(3/2)", 79 | "2", 80 | 81 | "ceiling(2/2)", 82 | "1", 83 | 84 | "ceiling(1/2)", 85 | "1", 86 | 87 | "ceiling(0/2)", 88 | "0", 89 | 90 | "ceiling(-1/2)", 91 | "0", 92 | 93 | "ceiling(-2/2)", 94 | "-1", 95 | 96 | "ceiling(-3/2)", 97 | "-1", 98 | 99 | "ceiling(-4/2)", 100 | "-2", 101 | 102 | "ceiling(-5/2)", 103 | "-2", 104 | 105 | "ceiling(5/2.0)", 106 | "3", 107 | 108 | "ceiling(4/2.0)", 109 | "2", 110 | 111 | "ceiling(3/2.0)", 112 | "2", 113 | 114 | "ceiling(2/2.0)", 115 | "1", 116 | 117 | "ceiling(1/2.0)", 118 | "1", 119 | 120 | "ceiling(0.0)", 121 | "0", 122 | 123 | "ceiling(-1/2.0)", 124 | "0", 125 | 126 | "ceiling(-2/2.0)", 127 | "-1", 128 | 129 | "ceiling(-3/2.0)", 130 | "-1", 131 | 132 | "ceiling(-4/2.0)", 133 | "-2", 134 | 135 | "ceiling(-5/2.0)", 136 | "-2", 137 | }; 138 | 139 | void 140 | test_ceiling(void) 141 | { 142 | test(__FILE__, s, sizeof s / sizeof (char *)); 143 | } 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /Eigenmath/Sources/choose.cpp: -------------------------------------------------------------------------------- 1 | // For example, the number of five card hands is choose(52,5) 2 | // 3 | // n! 4 | // choose(n,k) = ------------- 5 | // k! (n - k)! 6 | 7 | #include "../Headers/defs.h" 8 | 9 | void 10 | eval_choose(void) 11 | { 12 | push(cadr(p1)); 13 | eval(); 14 | push(caddr(p1)); 15 | eval(); 16 | choose(); 17 | } 18 | 19 | // Result vanishes for k < 0 or k > n. (A=B, p. 19) 20 | 21 | #define N p1 22 | #define K p2 23 | 24 | void 25 | choose(void) 26 | { 27 | save(); 28 | 29 | K = pop(); 30 | N = pop(); 31 | 32 | if (choose_check_args() == 0) 33 | { 34 | push_integer(0); 35 | restore(); 36 | return; 37 | } 38 | 39 | push(N); 40 | factorial(); 41 | 42 | push(K); 43 | factorial(); 44 | 45 | divide(); 46 | 47 | push(N); 48 | push(K); 49 | subtract(); 50 | factorial(); 51 | 52 | divide(); 53 | 54 | restore(); 55 | } 56 | 57 | int 58 | choose_check_args(void) 59 | { 60 | if (isnum(N) && lessp(N, zero)) 61 | return 0; 62 | else if (isnum(K) && lessp(K, zero)) 63 | return 0; 64 | else if (isnum(N) && isnum(K) && lessp(N, K)) 65 | return 0; 66 | else 67 | return 1; 68 | } 69 | 70 | #if SELFTEST 71 | 72 | static char *s[] = { 73 | 74 | "choose(52,5)", 75 | "2598960", 76 | 77 | "choose(n,k)", 78 | "n!/(k!*(-k+n)!)", 79 | 80 | "choose(0,k)", 81 | "1/(k!*(-k)!)", 82 | 83 | "choose(n,0)", 84 | "1", 85 | 86 | "choose(-1,k)", 87 | "0", 88 | 89 | "choose(n,-1)", 90 | "0", 91 | }; 92 | 93 | void 94 | test_choose(void) 95 | { 96 | test(__FILE__, s, sizeof s / sizeof (char *)); 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /Eigenmath/Sources/circexp.cpp: -------------------------------------------------------------------------------- 1 | // Change circular functions to exponentials 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_circexp(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | 11 | circexp(); 12 | 13 | // normalize 14 | 15 | eval(); 16 | } 17 | 18 | void 19 | circexp(void) 20 | { 21 | int i, h; 22 | save(); 23 | p1 = pop(); 24 | 25 | if (car(p1) == symbol(COS)) 26 | { 27 | push(cadr(p1)); 28 | expcos(); 29 | restore(); 30 | return; 31 | } 32 | 33 | if (car(p1) == symbol(SIN)) 34 | { 35 | push(cadr(p1)); 36 | expsin(); 37 | restore(); 38 | return; 39 | } 40 | 41 | if (car(p1) == symbol(TAN)) 42 | { 43 | p1 = cadr(p1); 44 | push(imaginaryunit); 45 | push(p1); 46 | multiply(); 47 | exponential(); 48 | p2 = pop(); 49 | push(imaginaryunit); 50 | push(p1); 51 | multiply(); 52 | negate(); 53 | exponential(); 54 | p3 = pop(); 55 | push(p3); 56 | push(p2); 57 | subtract(); 58 | push(imaginaryunit); 59 | multiply(); 60 | push(p2); 61 | push(p3); 62 | add(); 63 | divide(); 64 | restore(); 65 | return; 66 | } 67 | 68 | if (car(p1) == symbol(COSH)) 69 | { 70 | p1 = cadr(p1); 71 | push(p1); 72 | exponential(); 73 | push(p1); 74 | negate(); 75 | exponential(); 76 | add(); 77 | push_rational(1, 2); 78 | multiply(); 79 | restore(); 80 | return; 81 | } 82 | 83 | if (car(p1) == symbol(SINH)) 84 | { 85 | p1 = cadr(p1); 86 | push(p1); 87 | exponential(); 88 | push(p1); 89 | negate(); 90 | exponential(); 91 | subtract(); 92 | push_rational(1, 2); 93 | multiply(); 94 | restore(); 95 | return; 96 | } 97 | 98 | if (car(p1) == symbol(TANH)) 99 | { 100 | p1 = cadr(p1); 101 | push(p1); 102 | push_integer(2); 103 | multiply(); 104 | exponential(); 105 | p1 = pop(); 106 | push(p1); 107 | push_integer(1); 108 | subtract(); 109 | push(p1); 110 | push_integer(1); 111 | add(); 112 | divide(); 113 | restore(); 114 | return; 115 | } 116 | 117 | if (iscons(p1)) 118 | { 119 | h = tos; 120 | while (iscons(p1)) 121 | { 122 | push(car(p1)); 123 | circexp(); 124 | p1 = cdr(p1); 125 | } 126 | list(tos - h); 127 | restore(); 128 | return; 129 | } 130 | 131 | if (p1->k == TENSOR) 132 | { 133 | push(p1); 134 | copy_tensor(); 135 | p1 = pop(); 136 | for (i = 0; i < p1->u.tensor->nelem; i++) 137 | { 138 | push(p1->u.tensor->elem[i]); 139 | circexp(); 140 | p1->u.tensor->elem[i] = pop(); 141 | } 142 | push(p1); 143 | restore(); 144 | return; 145 | } 146 | 147 | push(p1); 148 | restore(); 149 | } 150 | 151 | #if SELFTEST 152 | 153 | static char *s[] = { 154 | 155 | "circexp(cos(x))", 156 | "1/2*exp(-i*x)+1/2*exp(i*x)", 157 | 158 | "circexp(sin(x))", 159 | "1/2*i*exp(-i*x)-1/2*i*exp(i*x)", 160 | 161 | "circexp(tan(x))", 162 | "i*exp(-i*x)/(exp(-i*x)+exp(i*x))-i*exp(i*x)/(exp(-i*x)+exp(i*x))", 163 | 164 | "circexp(cosh(x))", 165 | "1/2*exp(x)+1/2*exp(-x)", 166 | 167 | "circexp(sinh(x))", 168 | "1/2*exp(x)-1/2*exp(-x)", 169 | 170 | "circexp(tanh(x))", 171 | "-1/(1+exp(2*x))+exp(2*x)/(1+exp(2*x))", 172 | 173 | "circexp((cos(x),sin(x)))", 174 | "(1/2*exp(-i*x)+1/2*exp(i*x),1/2*i*exp(-i*x)-1/2*i*exp(i*x))", 175 | 176 | "circexp(cos(x)*sin(x))-expcos(x)*expsin(x)", 177 | "0", 178 | }; 179 | 180 | void 181 | test_circexp(void) 182 | { 183 | test(__FILE__, s, sizeof s / sizeof (char *)); 184 | } 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /Eigenmath/Sources/clear.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_clear(void) 6 | { 7 | if (test_flag == 0) 8 | clear_term(); 9 | clear_symbols(); 10 | defn(); 11 | push(symbol(NIL)); 12 | } 13 | 14 | // clear from application GUI code 15 | 16 | void 17 | clear(void) 18 | { 19 | run("clear"); 20 | } 21 | -------------------------------------------------------------------------------- /Eigenmath/Sources/clock.cpp: -------------------------------------------------------------------------------- 1 | /* Convert complex z to clock form 2 | 3 | Input: push z 4 | 5 | Output: Result on stack 6 | 7 | clock(z) = mag(z) * (-1) ^ (arg(z) / pi) 8 | 9 | For example, clock(exp(i pi/3)) gives the result (-1)^(1/3) 10 | */ 11 | 12 | #include "../Headers/defs.h" 13 | 14 | void 15 | eval_clock(void) 16 | { 17 | push(cadr(p1)); 18 | eval(); 19 | clockform(); 20 | } 21 | 22 | void 23 | clockform(void) 24 | { 25 | save(); 26 | #if 1 27 | p1 = pop(); 28 | push(p1); 29 | mag(); 30 | push_integer(-1); 31 | push(p1); 32 | arg(); 33 | push(symbol(PI)); 34 | divide(); 35 | power(); 36 | multiply(); 37 | #else 38 | p1 = pop(); 39 | push(p1); 40 | mag(); 41 | push(symbol(E)); 42 | push(p1); 43 | arg(); 44 | push(imaginaryunit); 45 | multiply(); 46 | power(); 47 | multiply(); 48 | #endif 49 | restore(); 50 | } 51 | 52 | #if SELFTEST 53 | 54 | static char *s[] = { 55 | 56 | "clock(exp(i pi/3))", 57 | "(-1)^(1/3)", 58 | 59 | "clock(exp(-i pi/3))", 60 | "-(-1)^(2/3)", 61 | 62 | "rect(clock(3+4*i))", // needs sin(arctan(x)) and cos(arctan(x)) 63 | "3+4*i", 64 | }; 65 | 66 | void 67 | test_clock(void) 68 | { 69 | test(__FILE__, s, sizeof s / sizeof (char *)); 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /Eigenmath/Sources/coeff.cpp: -------------------------------------------------------------------------------- 1 | // get the coefficient of x^n in polynomial p(x) 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define P p1 6 | #define X p2 7 | #define N p3 8 | 9 | void 10 | eval_coeff(void) 11 | { 12 | push(cadr(p1)); // 1st arg, p 13 | eval(); 14 | 15 | push(caddr(p1)); // 2nd arg, x 16 | eval(); 17 | 18 | push(cadddr(p1)); // 3rd arg, n 19 | eval(); 20 | 21 | N = pop(); 22 | X = pop(); 23 | P = pop(); 24 | 25 | if (N == symbol(NIL)) 26 | { // only 2 args? 27 | N = X; 28 | X = symbol(SYMBOL_X); 29 | } 30 | 31 | push(P); // divide p by x^n 32 | push(X); 33 | push(N); 34 | power(); 35 | divide(); 36 | 37 | push(X); // keep the constant part 38 | filter(); 39 | } 40 | 41 | //----------------------------------------------------------------------------- 42 | // 43 | // Put polynomial coefficients on the stack 44 | // 45 | // Input: tos-2 p(x) 46 | // 47 | // tos-1 x 48 | // 49 | // Output: Returns number of coefficients on stack 50 | // 51 | // tos-n Coefficient of x^0 52 | // 53 | // tos-1 Coefficient of x^(n-1) 54 | // 55 | //----------------------------------------------------------------------------- 56 | 57 | int 58 | coeff(void) 59 | { 60 | int h, n; 61 | 62 | save(); 63 | 64 | p2 = pop(); 65 | p1 = pop(); 66 | 67 | h = tos; 68 | 69 | for (;;) 70 | { 71 | 72 | push(p1); 73 | push(p2); 74 | push(zero); 75 | subst(); 76 | eval(); 77 | 78 | p3 = pop(); 79 | push(p3); 80 | 81 | push(p1); 82 | push(p3); 83 | subtract(); 84 | 85 | p1 = pop(); 86 | 87 | if (equal(p1, zero)) 88 | { 89 | n = tos - h; 90 | restore(); 91 | return n; 92 | } 93 | 94 | push(p1); 95 | push(p2); 96 | divide(); 97 | p1 = pop(); 98 | } 99 | } 100 | 101 | #if SELFTEST 102 | 103 | static char *s[] = { 104 | 105 | "coeff(40*x^3+30*x^2+20*x+10,3)", 106 | "40", 107 | 108 | "coeff(40*x^3+30*x^2+20*x+10,2)", 109 | "30", 110 | 111 | "coeff(40*x^3+30*x^2+20*x+10,1)", 112 | "20", 113 | 114 | "coeff(40*x^3+30*x^2+20*x+10,0)", 115 | "10", 116 | 117 | "coeff(a*t^3+b*t^2+c*t+d,t,3)", 118 | "a", 119 | 120 | "coeff(a*t^3+b*t^2+c*t+d,t,2)", 121 | "b", 122 | 123 | "coeff(a*t^3+b*t^2+c*t+d,t,1)", 124 | "c", 125 | 126 | "coeff(a*t^3+b*t^2+c*t+d,t,0)", 127 | "d", 128 | }; 129 | 130 | void 131 | test_coeff(void) 132 | { 133 | test(__FILE__, s, sizeof s / sizeof (char *)); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /Eigenmath/Sources/cofactor.cpp: -------------------------------------------------------------------------------- 1 | // Cofactor of a matrix component. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_cofactor(void) 7 | { 8 | int i, j, n; 9 | push(cadr(p1)); 10 | eval(); 11 | p2 = pop(); 12 | if (istensor(p2) && p2->u.tensor->ndim == 2 && p2->u.tensor->dim[0] == p2->u.tensor->dim[1]); 13 | else 14 | stop("cofactor: 1st arg: square matrix expected"); 15 | n = p2->u.tensor->dim[0]; 16 | push(caddr(p1)); 17 | eval(); 18 | i = pop_integer(); 19 | if (i < 1 || i > n) 20 | stop("cofactor: 2nd arg: row index expected"); 21 | push(cadddr(p1)); 22 | eval(); 23 | j = pop_integer(); 24 | if (j < 1 || j > n) 25 | stop("cofactor: 3rd arg: column index expected"); 26 | cofactor(p2, n, i - 1, j - 1); 27 | } 28 | 29 | void 30 | cofactor(U *p, int n, int row, int col) 31 | { 32 | int i, j; 33 | for (i = 0; i < n; i++) 34 | for (j = 0; j < n; j++) 35 | if (i != row && j != col) 36 | push(p->u.tensor->elem[n * i + j]); 37 | determinant(n - 1); 38 | if ((row + col) % 2) 39 | negate(); 40 | } 41 | 42 | #if SELFTEST 43 | 44 | static char *s[] = { 45 | 46 | "cofactor(((1,2),(3,4)),1,1)", 47 | "4", 48 | 49 | "cofactor(((1,2),(3,4)),1,2)", 50 | "-3", 51 | 52 | "cofactor(((1,2),(3,4)),2,1)", 53 | "-2", 54 | 55 | "cofactor(((1,2),(3,4)),2,2)", 56 | "1", 57 | 58 | "cofactor(((1,2,3),(4,5,6),(7,8,9)),1,2)", 59 | "6", 60 | }; 61 | 62 | void 63 | test_cofactor(void) 64 | { 65 | test(__FILE__, s, sizeof s / sizeof (char *)); 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Eigenmath/Sources/condense.cpp: -------------------------------------------------------------------------------- 1 | // Condense an expression by factoring common terms. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_condense(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | Condense(); 11 | } 12 | 13 | void 14 | Condense(void) 15 | { 16 | int tmp; 17 | tmp = expanding; 18 | save(); 19 | yycondense(); 20 | restore(); 21 | expanding = tmp; 22 | } 23 | 24 | void 25 | yycondense(void) 26 | { 27 | expanding = 0; 28 | 29 | p1 = pop(); 30 | 31 | if (car(p1) != symbol(ADD)) 32 | { 33 | push(p1); 34 | return; 35 | } 36 | 37 | // get gcd of all terms 38 | 39 | p3 = cdr(p1); 40 | push(car(p3)); 41 | p3 = cdr(p3); 42 | while (iscons(p3)) 43 | { 44 | push(car(p3)); 45 | gcd(); 46 | p3 = cdr(p3); 47 | } 48 | 49 | //printf("condense: this is the gcd of all the terms:\n"); 50 | //print(stdout, stack[tos - 1]); 51 | 52 | // divide each term by gcd 53 | 54 | inverse(); 55 | p2 = pop(); 56 | push(zero); 57 | p3 = cdr(p1); 58 | while (iscons(p3)) 59 | { 60 | push(p2); 61 | push(car(p3)); 62 | multiply(); 63 | add(); 64 | p3 = cdr(p3); 65 | } 66 | 67 | // We multiplied above w/o expanding so sum factors cancelled. 68 | 69 | // Now we expand which which normalizes the result and, in some cases, 70 | // simplifies it too (see test case H). 71 | 72 | yyexpand(); 73 | 74 | // multiply result by gcd 75 | 76 | push(p2); 77 | divide(); 78 | } 79 | 80 | #if SELFTEST 81 | 82 | static char *s[] = { 83 | 84 | "condense(a/(a+b)+b/(a+b))", 85 | "1", 86 | 87 | "psi(n) = exp(-r/n) laguerre(2r/n,n-1,1)", 88 | "", 89 | 90 | "psi(3)", 91 | "3*exp(-1/3*r)-2*r*exp(-1/3*r)+2/9*r^2*exp(-1/3*r)", 92 | 93 | "condense(last)", 94 | "exp(-1/3*r)*(3-2*r+2/9*r^2)", 95 | 96 | "psi()=psi", 97 | "", 98 | 99 | // test case H 100 | 101 | "condense(-3 exp(-1/3 r + i phi) cos(theta) - 6 exp(-1/3 r + i phi) cos(theta) sin(theta)^2 + 12 exp(-1/3 r + i phi) cos(theta)^3)", 102 | "3*exp(-1/3*r+i*phi)*(-1+4*cos(theta)^2-2*sin(theta)^2)*cos(theta)", 103 | }; 104 | 105 | void 106 | test_condense(void) 107 | { 108 | test(__FILE__, s, sizeof s / sizeof (char *)); 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /Eigenmath/Sources/conj.cpp: -------------------------------------------------------------------------------- 1 | // Complex conjugate 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_conj(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | p1 = pop(); 11 | push(p1); 12 | if (!find(p1, imaginaryunit)) 13 | { // example: (-1)^(1/3) 14 | polar(); 15 | conjugate(); 16 | clockform(); 17 | } 18 | else 19 | conjugate(); 20 | } 21 | 22 | void 23 | conjugate(void) 24 | { 25 | push(imaginaryunit); 26 | push(imaginaryunit); 27 | negate(); 28 | subst(); 29 | eval(); 30 | } 31 | -------------------------------------------------------------------------------- /Eigenmath/Sources/cons.cpp: -------------------------------------------------------------------------------- 1 | // Cons two things on the stack. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | cons(void) 7 | { 8 | // auto var ok, no opportunity for garbage collection after p = alloc() 9 | U *p; 10 | p = alloc(); 11 | p->k = CONS; 12 | p->u.cons.cdr = pop(); 13 | p->u.cons.car = pop(); 14 | push(p); 15 | } 16 | -------------------------------------------------------------------------------- /Eigenmath/Sources/contract.cpp: -------------------------------------------------------------------------------- 1 | // Contract across tensor indices 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_contract(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | if (cddr(p1) == symbol(NIL)) 11 | { 12 | push_integer(1); 13 | push_integer(2); 14 | } 15 | else 16 | { 17 | push(caddr(p1)); 18 | eval(); 19 | push(cadddr(p1)); 20 | eval(); 21 | } 22 | contract(); 23 | } 24 | 25 | void 26 | contract(void) 27 | { 28 | save(); 29 | yycontract(); 30 | restore(); 31 | } 32 | 33 | void 34 | yycontract(void) 35 | { 36 | int h, i, j, k, l, m, n, ndim, nelem; 37 | int ai[MAXDIM], an[MAXDIM]; 38 | U **a, **b; 39 | 40 | p3 = pop(); 41 | p2 = pop(); 42 | p1 = pop(); 43 | 44 | if (!istensor(p1)) 45 | { 46 | if (!iszero(p1)) 47 | stop("contract: tensor expected, 1st arg is not a tensor"); 48 | push(zero); 49 | return; 50 | } 51 | 52 | push(p2); 53 | l = pop_integer(); 54 | 55 | push(p3); 56 | m = pop_integer(); 57 | 58 | ndim = p1->u.tensor->ndim; 59 | 60 | if (l < 1 || l > ndim || m < 1 || m > ndim || l == m 61 | || p1->u.tensor->dim[l - 1] != p1->u.tensor->dim[m - 1]) 62 | stop("contract: index out of range"); 63 | 64 | l--; 65 | m--; 66 | 67 | n = p1->u.tensor->dim[l]; 68 | 69 | // nelem is the number of elements in "b" 70 | 71 | nelem = 1; 72 | for (i = 0; i < ndim; i++) 73 | if (i != l && i != m) 74 | nelem *= p1->u.tensor->dim[i]; 75 | 76 | p2 = alloc_tensor(nelem); 77 | 78 | p2->u.tensor->ndim = ndim - 2; 79 | 80 | j = 0; 81 | for (i = 0; i < ndim; i++) 82 | if (i != l && i != m) 83 | p2->u.tensor->dim[j++] = p1->u.tensor->dim[i]; 84 | 85 | a = p1->u.tensor->elem; 86 | b = p2->u.tensor->elem; 87 | 88 | for (i = 0; i < ndim; i++) 89 | { 90 | ai[i] = 0; 91 | an[i] = p1->u.tensor->dim[i]; 92 | } 93 | 94 | for (i = 0; i < nelem; i++) 95 | { 96 | push(zero); 97 | for (j = 0; j < n; j++) 98 | { 99 | ai[l] = j; 100 | ai[m] = j; 101 | h = 0; 102 | for (k = 0; k < ndim; k++) 103 | h = (h * an[k]) + ai[k]; 104 | push(a[h]); 105 | add(); 106 | } 107 | b[i] = pop(); 108 | for (j = ndim - 1; j >= 0; j--) 109 | { 110 | if (j == l || j == m) 111 | continue; 112 | if (++ai[j] < an[j]) 113 | break; 114 | ai[j] = 0; 115 | } 116 | } 117 | 118 | if (nelem == 1) 119 | push(b[0]); 120 | else 121 | push(p2); 122 | } 123 | 124 | #if SELFTEST 125 | 126 | static char *s[] = { 127 | 128 | "contract(0)", 129 | "0", 130 | 131 | "contract(0.0)", 132 | "0", 133 | 134 | "contract(((a,b),(c,d)))", 135 | "a+d", 136 | 137 | "contract(((1,2),(3,4)),1,2)", 138 | "5", 139 | 140 | "A=((a11,a12),(a21,a22))", 141 | "", 142 | 143 | "B=((b11,b12),(b21,b22))", 144 | "", 145 | 146 | "contract(outer(A,B),2,3)", 147 | "((a11*b11+a12*b21,a11*b12+a12*b22),(a21*b11+a22*b21,a21*b12+a22*b22))", 148 | 149 | "A=quote(A)", 150 | "", 151 | 152 | "B=quote(B)", 153 | "", 154 | }; 155 | 156 | void 157 | test_contract(void) 158 | { 159 | test(__FILE__, s, sizeof s / sizeof (char *)); 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /Eigenmath/Sources/cosh.cpp: -------------------------------------------------------------------------------- 1 | // exp(x) + exp(-x) 2 | // cosh(x) = ---------------- 3 | // 2 4 | 5 | #include "../Headers/defs.h" 6 | 7 | void 8 | eval_cosh(void) 9 | { 10 | push(cadr(p1)); 11 | eval(); 12 | ycosh(); 13 | } 14 | 15 | void 16 | ycosh(void) 17 | { 18 | save(); 19 | yycosh(); 20 | restore(); 21 | } 22 | 23 | void 24 | yycosh(void) 25 | { 26 | double d; 27 | p1 = pop(); 28 | if (car(p1) == symbol(ARCCOSH)) 29 | { 30 | push(cadr(p1)); 31 | return; 32 | } 33 | if (isdouble(p1)) 34 | { 35 | d = cosh(p1->u.d); 36 | if (fabs(d) < 1e-10) 37 | d = 0.0; 38 | push_double(d); 39 | return; 40 | } 41 | if (iszero(p1)) 42 | { 43 | push(one); 44 | return; 45 | } 46 | push_symbol(COSH); 47 | push(p1); 48 | list(2); 49 | } 50 | 51 | #if SELFTEST 52 | 53 | static char *s[] = { 54 | 55 | "cosh(x)", 56 | "cosh(x)", 57 | 58 | "cosh(0)", 59 | "1", 60 | 61 | "cosh(arccosh(x))", 62 | "x", 63 | }; 64 | 65 | void 66 | test_cosh(void) 67 | { 68 | test(__FILE__, s, sizeof s / sizeof (char *)); 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /Eigenmath/Sources/data.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | int endian = 1; 5 | 6 | U *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; 7 | 8 | U *zero, *one, *imaginaryunit; 9 | 10 | U symtab[NSYM], *binding[NSYM], *arglist[NSYM]; 11 | 12 | int expanding; 13 | int verbosing; 14 | int esc_flag; 15 | int test_flag; 16 | int draw_flag; 17 | int trigmode; 18 | //char logbuf[1000]; 19 | -------------------------------------------------------------------------------- /Eigenmath/Sources/decomp.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_decomp(void) 6 | { 7 | int h = tos; 8 | push(symbol(NIL)); 9 | push(cadr(p1)); 10 | eval(); 11 | push(caddr(p1)); 12 | eval(); 13 | p1 = pop(); 14 | if (p1 == symbol(NIL)) 15 | guess(); 16 | else 17 | push(p1); 18 | decomp(); 19 | list(tos - h); 20 | } 21 | 22 | // returns constant expresions on the stack 23 | 24 | void 25 | decomp(void) 26 | { 27 | save(); 28 | 29 | p2 = pop(); 30 | p1 = pop(); 31 | 32 | // is the entire expression constant? 33 | 34 | if (find(p1, p2) == 0) 35 | { 36 | push(p1); 37 | //push(p1); // may need later for pushing both +a, -a 38 | //negate(); 39 | restore(); 40 | return; 41 | } 42 | 43 | // sum? 44 | 45 | if (isadd(p1)) 46 | { 47 | decomp_sum(); 48 | restore(); 49 | return; 50 | } 51 | 52 | // product? 53 | 54 | if (car(p1) == symbol(MULTIPLY)) 55 | { 56 | decomp_product(); 57 | restore(); 58 | return; 59 | } 60 | 61 | // naive decomp if not sum or product 62 | 63 | p3 = cdr(p1); 64 | while (iscons(p3)) 65 | { 66 | push(car(p3)); 67 | push(p2); 68 | decomp(); 69 | p3 = cdr(p3); 70 | } 71 | 72 | restore(); 73 | } 74 | 75 | void 76 | decomp_sum(void) 77 | { 78 | int h; 79 | 80 | // decomp terms involving x 81 | 82 | p3 = cdr(p1); 83 | 84 | while (iscons(p3)) 85 | { 86 | if (find(car(p3), p2)) 87 | { 88 | push(car(p3)); 89 | push(p2); 90 | decomp(); 91 | } 92 | p3 = cdr(p3); 93 | } 94 | 95 | // add together all constant terms 96 | 97 | h = tos; 98 | 99 | p3 = cdr(p1); 100 | 101 | while (iscons(p3)) 102 | { 103 | if (find(car(p3), p2) == 0) 104 | push(car(p3)); 105 | p3 = cdr(p3); 106 | } 107 | 108 | if (tos - h) 109 | { 110 | add_all(tos - h); 111 | p3 = pop(); 112 | push(p3); 113 | push(p3); 114 | negate(); // need both +a, -a for some integrals 115 | } 116 | } 117 | 118 | void 119 | decomp_product(void) 120 | { 121 | int h; 122 | 123 | // decomp factors involving x 124 | 125 | p3 = cdr(p1); 126 | 127 | while (iscons(p3)) 128 | { 129 | if (find(car(p3), p2)) 130 | { 131 | push(car(p3)); 132 | push(p2); 133 | decomp(); 134 | } 135 | p3 = cdr(p3); 136 | } 137 | 138 | // multiply together all constant factors 139 | 140 | h = tos; 141 | 142 | p3 = cdr(p1); 143 | 144 | while (iscons(p3)) 145 | { 146 | if (find(car(p3), p2) == 0) 147 | push(car(p3)); 148 | p3 = cdr(p3); 149 | } 150 | 151 | if (tos - h) 152 | { 153 | multiply_all(tos - h); 154 | //p3 = pop(); // may need later for pushing both +a, -a 155 | //push(p3); 156 | //push(p3); 157 | //negate(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Eigenmath/Sources/define.cpp: -------------------------------------------------------------------------------- 1 | // Store a function definition 2 | // 3 | // Example: 4 | // 5 | // f(x,y)=x^y 6 | // 7 | // For this definition, p1 points to the following structure. 8 | // 9 | // p1 10 | // | 11 | // ___v__ ______ ______ 12 | // |CONS |->|CONS |--------------------->|CONS | 13 | // |______| |______| |______| 14 | // | | | 15 | // ___v__ ___v__ ______ ______ ___v__ ______ ______ 16 | // |SETQ | |CONS |->|CONS |->|CONS | |CONS |->|CONS |->|CONS | 17 | // |______| |______| |______| |______| |______| |______| |______| 18 | // | | | | | | 19 | // ___v__ ___v__ ___v__ ___v__ ___v__ ___v__ 20 | // |SYM f | |SYM x | |SYM y | |POWER | |SYM x | |SYM y | 21 | // |______| |______| |______| |______| |______| |______| 22 | // 23 | // We have 24 | // 25 | // caadr(p1) points to f 26 | // cdadr(p1) points to the list (x y) 27 | // caddr(p1) points to (power x y) 28 | 29 | #include "../Headers/defs.h" 30 | 31 | #define F p3 // F points to the function name 32 | #define A p4 // A points to the argument list 33 | #define B p5 // B points to the function body 34 | 35 | void 36 | define_user_function(void) 37 | { 38 | F = caadr(p1); 39 | A = cdadr(p1); 40 | B = caddr(p1); 41 | 42 | if (!issymbol(F)) 43 | stop("function name?"); 44 | 45 | // evaluate function body (maybe) 46 | 47 | if (car(B) == symbol(EVAL)) 48 | { 49 | push(cadr(B)); 50 | eval(); 51 | B = pop(); 52 | } 53 | 54 | set_binding_and_arglist(F, B, A); 55 | 56 | // return value is nil 57 | 58 | push_symbol(NIL); 59 | } 60 | -------------------------------------------------------------------------------- /Eigenmath/Sources/defint.cpp: -------------------------------------------------------------------------------- 1 | // definite integral 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define F p2 6 | #define X p3 7 | #define A p4 8 | #define B p5 9 | 10 | void 11 | eval_defint(void) 12 | { 13 | push(cadr(p1)); 14 | eval(); 15 | F = pop(); 16 | 17 | p1 = cddr(p1); 18 | 19 | while (iscons(p1)) 20 | { 21 | 22 | push(car(p1)); 23 | p1 = cdr(p1); 24 | eval(); 25 | X = pop(); 26 | 27 | push(car(p1)); 28 | p1 = cdr(p1); 29 | eval(); 30 | A = pop(); 31 | 32 | push(car(p1)); 33 | p1 = cdr(p1); 34 | eval(); 35 | B = pop(); 36 | 37 | push(F); 38 | push(X); 39 | integral(); 40 | F = pop(); 41 | 42 | push(F); 43 | push(X); 44 | push(B); 45 | subst(); 46 | eval(); 47 | 48 | push(F); 49 | push(X); 50 | push(A); 51 | subst(); 52 | eval(); 53 | 54 | subtract(); 55 | F = pop(); 56 | } 57 | 58 | push(F); 59 | } 60 | 61 | #if SELFTEST 62 | 63 | static char *s[] = { 64 | "defint(x^2,y,0,sqrt(1-x^2),x,-1,1)", 65 | "1/8*pi", 66 | 67 | // from the eigenmath manual 68 | 69 | "z=2", 70 | "", 71 | 72 | "P=(x,y,z)", 73 | "", 74 | 75 | "a=abs(cross(d(P,x),d(P,y)))", 76 | "", 77 | 78 | "defint(a,y,-sqrt(1-x^2),sqrt(1-x^2),x,-1,1)", 79 | "pi", 80 | 81 | // from the eigenmath manual 82 | 83 | "z=x^2+2y", 84 | "", 85 | 86 | "P=(x,y,z)", 87 | "", 88 | 89 | "a=abs(cross(d(P,x),d(P,y)))", 90 | "", 91 | 92 | "defint(a,x,0,1,y,0,1)", 93 | "3/2+5/8*log(5)", 94 | 95 | // from the eigenmath manual 96 | 97 | "x=u*cos(v)", 98 | "", 99 | 100 | "y=u*sin(v)", 101 | "", 102 | 103 | "z=v", 104 | "", 105 | 106 | "S=(x,y,z)", 107 | "", 108 | 109 | "a=abs(cross(d(S,u),d(S,v)))", 110 | "", 111 | 112 | "defint(a,u,0,1,v,0,3pi)", 113 | "3/2*pi*log(1+2^(1/2))+3*pi/(2^(1/2))", 114 | }; 115 | 116 | void 117 | test_defint(void) 118 | { 119 | test(__FILE__, s, sizeof s / sizeof (char *)); 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /Eigenmath/Sources/degree.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_degree(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | push(caddr(p1)); 10 | eval(); 11 | p1 = pop(); 12 | if (p1 == symbol(NIL)) 13 | guess(); 14 | else 15 | push(p1); 16 | degree(); 17 | } 18 | 19 | //----------------------------------------------------------------------------- 20 | // 21 | // Find the degree of a polynomial 22 | // 23 | // Input: tos-2 p(x) 24 | // 25 | // tos-1 x 26 | // 27 | // Output: Result on stack 28 | // 29 | // Note: Finds the largest numerical power of x. Does not check for 30 | // weirdness in p(x). 31 | // 32 | //----------------------------------------------------------------------------- 33 | 34 | #define POLY p1 35 | #define X p2 36 | #define DEGREE p3 37 | 38 | void 39 | degree(void) 40 | { 41 | save(); 42 | X = pop(); 43 | POLY = pop(); 44 | DEGREE = zero; 45 | yydegree(POLY); 46 | push(DEGREE); 47 | restore(); 48 | } 49 | 50 | void 51 | yydegree(U *p) 52 | { 53 | if (equal(p, X)) 54 | { 55 | if (iszero(DEGREE)) 56 | DEGREE = one; 57 | } 58 | else if (car(p) == symbol(POWER)) 59 | { 60 | if (equal(cadr(p), X) && isnum(caddr(p)) && lessp(DEGREE, caddr(p))) 61 | DEGREE = caddr(p); 62 | } 63 | else if (iscons(p)) 64 | { 65 | p = cdr(p); 66 | while (iscons(p)) 67 | { 68 | yydegree(car(p)); 69 | p = cdr(p); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Eigenmath/Sources/denominator.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_denominator(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | denominator(); 10 | } 11 | 12 | void 13 | denominator(void) 14 | { 15 | int h; 16 | 17 | save(); 18 | 19 | p1 = pop(); 20 | 21 | if (car(p1) == symbol(ADD)) 22 | { 23 | push(p1); 24 | rationalize(); 25 | p1 = pop(); 26 | } 27 | 28 | if (car(p1) == symbol(MULTIPLY)) 29 | { 30 | h = tos; 31 | p1 = cdr(p1); 32 | while (iscons(p1)) 33 | { 34 | push(car(p1)); 35 | denominator(); 36 | p1 = cdr(p1); 37 | } 38 | multiply_all(tos - h); 39 | } 40 | else if (isrational(p1)) 41 | { 42 | push(p1); 43 | mp_denominator(); 44 | } 45 | else if (car(p1) == symbol(POWER) && isnegativeterm(caddr(p1))) 46 | { 47 | push(p1); 48 | reciprocate(); 49 | } 50 | else 51 | push(one); 52 | 53 | restore(); 54 | } 55 | 56 | #if SELFTEST 57 | 58 | static char *s[] = { 59 | 60 | "denominator(2/3)", 61 | "3", 62 | 63 | "denominator(x)", 64 | "1", 65 | 66 | "denominator(1/x)", 67 | "x", 68 | 69 | "denominator(a+b)", 70 | "1", 71 | 72 | "denominator(1/a+1/b)", 73 | "a*b", 74 | 75 | // denominator function expands 76 | 77 | "denominator(1/(x-1)/(x-2))", 78 | "x^2-3*x+2", 79 | }; 80 | 81 | void 82 | test_denominator(void) 83 | { 84 | test(__FILE__, s, sizeof s / sizeof (char *)); 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /Eigenmath/Sources/dirac.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Author : philippe.billet@noos.fr 4 | // 5 | // Dirac function dirac(x) 6 | // dirac(-x)=dirac(x) 7 | // dirac(b-a)=dirac(a-b) 8 | //----------------------------------------------------------------------------- 9 | 10 | #include "../Headers/defs.h" 11 | 12 | static void ydirac(void); 13 | 14 | void 15 | eval_dirac(void) 16 | { 17 | push(cadr(p1)); 18 | eval(); 19 | dirac(); 20 | } 21 | 22 | void 23 | dirac(void) 24 | { 25 | save(); 26 | ydirac(); 27 | restore(); 28 | } 29 | 30 | #define X p1 31 | 32 | static void 33 | ydirac(void) 34 | { 35 | 36 | X = pop(); 37 | 38 | if (isdouble(X)) 39 | { 40 | if (X->u.d == 0) 41 | { 42 | push_integer(1); 43 | return; 44 | } 45 | else 46 | { 47 | push_integer(0); 48 | return; 49 | } 50 | } 51 | 52 | if (isrational(X)) 53 | { 54 | if (MZERO(mmul(X->u.q.a, X->u.q.b))) 55 | { 56 | push_integer(1); 57 | return; 58 | } 59 | else 60 | { 61 | push_integer(0); 62 | return; 63 | } 64 | 65 | } 66 | 67 | if (car(X) == symbol(POWER)) 68 | { 69 | push_symbol(DIRAC); 70 | push(cadr(X)); 71 | list(2); 72 | return; 73 | } 74 | 75 | if (isnegativeterm(X)) 76 | { 77 | push_symbol(DIRAC); 78 | push(X); 79 | negate(); 80 | list(2); 81 | return; 82 | } 83 | 84 | if (isnegativeterm(p1) || (car(p1) == symbol(ADD) && isnegativeterm(cadr(p1)))) 85 | { 86 | push(p1); 87 | negate(); 88 | p1 = pop(); 89 | } 90 | 91 | push_symbol(DIRAC); 92 | push(X); 93 | list(2); 94 | } 95 | 96 | #if SELFTEST 97 | 98 | static char *s[] = { 99 | 100 | 101 | "dirac(-x)", 102 | "dirac(x)", 103 | }; 104 | 105 | void 106 | test_dirac(void) 107 | { 108 | test(__FILE__, s, sizeof s / sizeof (char *)); 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /Eigenmath/Sources/display.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Examples: 4 | // 5 | // 012345678 6 | // -2 ......... 7 | // -1 ......... 8 | // 0 ..hello.. x=2, y=0, h=1, w=5 9 | // 1 ......... 10 | // 2 ......... 11 | // 12 | // 012345678 13 | // -2 ......... 14 | // -1 ..355.... 15 | // 0 ..---.... x=2, y=-1, h=3, w=3 16 | // 1 ..113.... 17 | // 2 ......... 18 | // 19 | //----------------------------------------------------------------------------- 20 | 21 | #include "../Headers/defs.h" 22 | 23 | void 24 | display(U *p) 25 | { 26 | //save(); 27 | printline(p); 28 | //restore(); 29 | } 30 | -------------------------------------------------------------------------------- /Eigenmath/Sources/distill.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "../Headers/defs.h" 4 | 5 | static void _distill(void); 6 | 7 | // take expr and push all constant subexpr 8 | 9 | // p1 expr 10 | 11 | // p2 independent variable (like x) 12 | 13 | void 14 | distill(void) 15 | { 16 | save(); 17 | _distill(); 18 | restore(); 19 | } 20 | 21 | static void 22 | _distill(void) 23 | { 24 | p2 = pop(); 25 | p1 = pop(); 26 | 27 | // is the entire expression constant? 28 | 29 | if (find(p1, p2) == 0) 30 | { 31 | push(p1); 32 | //push(p1); // may need later for pushing both +a, -a 33 | //negate(); 34 | return; 35 | } 36 | 37 | // sum? 38 | 39 | if (isadd(p1)) 40 | { 41 | distill_sum(); 42 | return; 43 | } 44 | 45 | // product? 46 | 47 | if (car(p1) == symbol(MULTIPLY)) 48 | { 49 | distill_product(); 50 | return; 51 | } 52 | 53 | // naive distill if not sum or product 54 | 55 | p3 = cdr(p1); 56 | while (iscons(p3)) 57 | { 58 | push(car(p3)); 59 | push(p2); 60 | distill(); 61 | p3 = cdr(p3); 62 | } 63 | } 64 | 65 | void 66 | distill_sum(void) 67 | { 68 | int h; 69 | 70 | // distill terms involving x 71 | 72 | p3 = cdr(p1); 73 | 74 | while (iscons(p3)) 75 | { 76 | if (find(car(p3), p2)) 77 | { 78 | push(car(p3)); 79 | push(p2); 80 | distill(); 81 | } 82 | p3 = cdr(p3); 83 | } 84 | 85 | // add together all constant terms 86 | 87 | h = tos; 88 | 89 | p3 = cdr(p1); 90 | 91 | while (iscons(p3)) 92 | { 93 | if (find(car(p3), p2) == 0) 94 | push(car(p3)); 95 | p3 = cdr(p3); 96 | } 97 | 98 | if (tos - h) 99 | { 100 | add_all(tos - h); 101 | p3 = pop(); 102 | push(p3); 103 | push(p3); 104 | negate(); // need both +a, -a for some integrals 105 | } 106 | } 107 | 108 | void 109 | distill_product(void) 110 | { 111 | int h; 112 | 113 | // distill factors involving x 114 | 115 | p3 = cdr(p1); 116 | 117 | while (iscons(p3)) 118 | { 119 | if (find(car(p3), p2)) 120 | { 121 | push(car(p3)); 122 | push(p2); 123 | distill(); 124 | } 125 | p3 = cdr(p3); 126 | } 127 | 128 | // multiply together all constant factors 129 | 130 | h = tos; 131 | 132 | p3 = cdr(p1); 133 | 134 | while (iscons(p3)) 135 | { 136 | if (find(car(p3), p2) == 0) 137 | push(car(p3)); 138 | p3 = cdr(p3); 139 | } 140 | 141 | if (tos - h) 142 | { 143 | multiply_all(tos - h); 144 | //p3 = pop(); // may need later for pushing both +a, -a 145 | //push(p3); 146 | //push(p3); 147 | //negate(); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Eigenmath/Sources/dpow.cpp: -------------------------------------------------------------------------------- 1 | // power function for double precision floating point 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | dpow(void) 7 | { 8 | double a, b, base, expo, result, theta; 9 | 10 | expo = pop_double(); 11 | base = pop_double(); 12 | 13 | // divide by zero? 14 | 15 | if (base == 0.0 && expo < 0.0) 16 | stop("divide by zero"); 17 | 18 | // nonnegative base or integer power? 19 | 20 | if (base >= 0.0 || fmod(expo, 1.0) == 0.0) 21 | { 22 | result = pow(base, expo); 23 | push_double(result); 24 | return; 25 | } 26 | 27 | result = pow(fabs(base), expo); 28 | 29 | theta = M_PI * expo; 30 | 31 | // this ensures the real part is 0.0 instead of a tiny fraction 32 | 33 | if (fmod(expo, 0.5) == 0.0) 34 | { 35 | a = 0.0; 36 | b = sin(theta); 37 | } 38 | else 39 | { 40 | a = cos(theta); 41 | b = sin(theta); 42 | } 43 | 44 | push_double(a * result); 45 | push_double(b * result); 46 | push(imaginaryunit); 47 | multiply(); 48 | add(); 49 | } 50 | -------------------------------------------------------------------------------- /Eigenmath/Sources/dsolve.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "../Headers/defs.h" 4 | 5 | // q(x)y' + p(x)*y = g(x) 6 | // 7 | // u(x) = exp(integral(p)) 8 | // 9 | // y = (integral(u*g) + c) / u(x) 10 | 11 | 12 | #define f p1 13 | #define y p2 14 | #define x p3 15 | 16 | #define p p4 17 | #define g p5 18 | #define q p6 19 | 20 | #define mu p7 21 | 22 | void 23 | dsolve(void) 24 | { 25 | int n; 26 | 27 | save(); 28 | 29 | x = pop(); 30 | y = pop(); 31 | f = pop(); 32 | 33 | push(f); 34 | push(y); 35 | push(x); 36 | 37 | n = distilly(); 38 | 39 | if (n != 3) 40 | stop("error in dsolve"); 41 | 42 | q = pop(); 43 | 44 | p = pop(); 45 | 46 | negate(); 47 | g = pop(); 48 | 49 | /* print(g); 50 | print(p); 51 | print(p); 52 | */ 53 | push(p); 54 | push(q); 55 | divide(); 56 | push(x); 57 | integral(); 58 | exponential(); 59 | mu = pop(); 60 | 61 | push(mu); 62 | push(g); 63 | push(q); 64 | divide(); 65 | multiply(); 66 | push(x); 67 | integral(); 68 | scan("C"); 69 | add(); 70 | push(mu); 71 | divide(); 72 | 73 | restore(); 74 | } 75 | 76 | // n p1 p2 p3 p4 p5 stack 77 | 78 | // 1 4y'+3xy+2x+1 y x 1 2x+1 2x+1 79 | 80 | // 2 4y'+3xy y' x y 3xy 3x 81 | 82 | // 3 4y' y'' x y' 4y' 4 83 | 84 | int distilly() 85 | { 86 | int n = 0; 87 | save(); 88 | p4 = one; 89 | p3 = pop(); 90 | p2 = pop(); 91 | p1 = pop(); 92 | while (1) 93 | { 94 | n++; 95 | push(p1); 96 | push(p2); 97 | push(zero); 98 | subst(); 99 | eval(); 100 | p5 = pop(); 101 | push(p5); 102 | push(p4); 103 | divide(); 104 | push(p1); 105 | push(p5); 106 | subtract(); 107 | p1 = pop(); 108 | if (equal(p1, zero)) 109 | break; 110 | p4 = p2; 111 | push(p2); 112 | push(p3); 113 | derivative(); 114 | p2 = pop(); 115 | } 116 | restore(); 117 | return n; 118 | } 119 | -------------------------------------------------------------------------------- /Eigenmath/Sources/eigenmath.cpp: -------------------------------------------------------------------------------- 1 | /* Eigenmath by G. Weigt 2 | 3 | The starting point for a symbolic computation is in run.cpp 4 | 5 | Input is scanned in scan.cpp 6 | 7 | Expression evaluation is done in eval.cpp 8 | 9 | Output is formatted in display.cpp 10 | */ 11 | 12 | #include "../Headers/defs.h" 13 | 14 | void 15 | clear_term() 16 | { 17 | 18 | } 19 | 20 | extern void eval_print(void); 21 | 22 | void 23 | eval_display(void) 24 | { 25 | eval_print(); 26 | } 27 | 28 | extern int test_flag; 29 | 30 | void 31 | printchar_nowrap(int c) 32 | { 33 | printchar(c); 34 | } 35 | 36 | void 37 | eval_draw(void) 38 | { 39 | push(symbol(NIL)); 40 | } 41 | 42 | void 43 | eval_sample(void) 44 | { 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Eigenmath/Sources/erf.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Author : philippe.billet@noos.fr 4 | // 5 | // Error function erf(x) 6 | // erf(-x)=erf(x) 7 | // 8 | //----------------------------------------------------------------------------- 9 | 10 | #include "../Headers/defs.h" 11 | 12 | static void yyerf(void); 13 | 14 | void 15 | eval_erf(void) 16 | { 17 | push(cadr(p1)); 18 | eval(); 19 | yerf(); 20 | } 21 | 22 | void 23 | yerf(void) 24 | { 25 | save(); 26 | yyerf(); 27 | restore(); 28 | } 29 | 30 | static void 31 | yyerf(void) 32 | { 33 | double d; 34 | 35 | p1 = pop(); 36 | 37 | if (isdouble(p1)) 38 | { 39 | d = 1.0 - erfc(p1->u.d); 40 | push_double(d); 41 | return; 42 | } 43 | 44 | if (isnegativeterm(p1)) 45 | { 46 | push_symbol(ERF); 47 | push(p1); 48 | negate(); 49 | list(2); 50 | negate(); 51 | return; 52 | } 53 | 54 | push_symbol(ERF); 55 | push(p1); 56 | list(2); 57 | return; 58 | } 59 | 60 | #if SELFTEST 61 | 62 | static char *s[] = { 63 | 64 | "erf(a)", 65 | "erf(a)", 66 | 67 | "erf(0.0) + 1", // add 1 to round off 68 | "1", 69 | 70 | "float(erf(0)) + 1", // add 1 to round off 71 | "1", 72 | #if 0 73 | "float(erf(1))", 74 | "0.842701", 75 | #endif 76 | }; 77 | 78 | void 79 | test_erf(void) 80 | { 81 | test(__FILE__, s, sizeof s / sizeof (char *)); 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /Eigenmath/Sources/erfc.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Author : philippe.billet@noos.fr 4 | // 5 | // erfc(x) 6 | // 7 | // GW Added erfc() from Numerical Recipes in C 8 | // 9 | //----------------------------------------------------------------------------- 10 | 11 | #include "../Headers/defs.h" 12 | 13 | static void yyerfc(void); 14 | 15 | void 16 | eval_erfc(void) 17 | { 18 | push(cadr(p1)); 19 | eval(); 20 | yerfc(); 21 | } 22 | 23 | void 24 | yerfc(void) 25 | { 26 | save(); 27 | yyerfc(); 28 | restore(); 29 | } 30 | 31 | static void 32 | yyerfc(void) 33 | { 34 | double d; 35 | 36 | p1 = pop(); 37 | 38 | if (isdouble(p1)) 39 | { 40 | d = erfc(p1->u.d); 41 | push_double(d); 42 | return; 43 | } 44 | 45 | push_symbol(ERFC); 46 | push(p1); 47 | list(2); 48 | return; 49 | } 50 | 51 | // from Numerical Recipes in C 52 | 53 | #ifndef LINUX 54 | double 55 | erfc(double x) 56 | { 57 | double t, z, ans; 58 | z = fabs(x); 59 | t = 1.0 / (1.0 + 0.5 * z); 60 | 61 | ans = t * exp(-z * z - 1.26551223 + t * (1.00002368 + t * (0.37409196 + t * (0.09678418 + 62 | t * (-0.18628806 + t * (0.27886807 + t * (-1.13520398 + t * (1.48851587 + 63 | t * (-0.82215223 + t * 0.17087277))))))))); 64 | 65 | return x >= 0.0 ? ans : 2.0 - ans; 66 | } 67 | #endif 68 | 69 | #if SELFTEST 70 | 71 | static char *s[] = { 72 | 73 | "erfc(a)", 74 | "erfc(a)", 75 | 76 | "erfc(0.0)", 77 | "1", 78 | 79 | "float(erfc(0))", 80 | "1", 81 | #if 0 82 | "float(erfc(1))", 83 | "0.157299", 84 | #endif 85 | }; 86 | 87 | void 88 | test_erfc(void) 89 | { 90 | test(__FILE__, s, sizeof s / sizeof (char *)); 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /Eigenmath/Sources/expcos.cpp: -------------------------------------------------------------------------------- 1 | // Do the exponential cosine function. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_expcos(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | expcos(); 11 | } 12 | 13 | void 14 | expcos(void) 15 | { 16 | save(); 17 | 18 | p1 = pop(); 19 | 20 | push(imaginaryunit); 21 | push(p1); 22 | multiply(); 23 | exponential(); 24 | push_rational(1, 2); 25 | multiply(); 26 | 27 | push(imaginaryunit); 28 | negate(); 29 | push(p1); 30 | multiply(); 31 | exponential(); 32 | push_rational(1, 2); 33 | multiply(); 34 | 35 | add(); 36 | 37 | restore(); 38 | } 39 | 40 | #if SELFTEST 41 | 42 | static char *s[] = { 43 | 44 | "expcos(x)", 45 | "1/2*exp(-i*x)+1/2*exp(i*x)", 46 | }; 47 | 48 | void 49 | test_expcos(void) 50 | { 51 | test(__FILE__, s, sizeof s / sizeof (char *)); 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Eigenmath/Sources/expsin.cpp: -------------------------------------------------------------------------------- 1 | // Do the exponential sine function. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_expsin(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | expsin(); 11 | } 12 | 13 | void 14 | expsin(void) 15 | { 16 | save(); 17 | 18 | p1 = pop(); 19 | 20 | push(imaginaryunit); 21 | push(p1); 22 | multiply(); 23 | exponential(); 24 | push(imaginaryunit); 25 | divide(); 26 | push_rational(1, 2); 27 | multiply(); 28 | 29 | push(imaginaryunit); 30 | negate(); 31 | push(p1); 32 | multiply(); 33 | exponential(); 34 | push(imaginaryunit); 35 | divide(); 36 | push_rational(1, 2); 37 | multiply(); 38 | 39 | subtract(); 40 | 41 | restore(); 42 | } 43 | 44 | #if SELFTEST 45 | 46 | static char *s[] = { 47 | 48 | "expsin(x)", 49 | "1/2*i*exp(-i*x)-1/2*i*exp(i*x)", 50 | }; 51 | 52 | void 53 | test_expsin(void) 54 | { 55 | test(__FILE__, s, sizeof s / sizeof (char *)); 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /Eigenmath/Sources/factor.cpp: -------------------------------------------------------------------------------- 1 | // factor a polynomial or integer 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_factor(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | 11 | push(caddr(p1)); 12 | eval(); 13 | 14 | p2 = pop(); 15 | if (p2 == symbol(NIL)) 16 | guess(); 17 | else 18 | push(p2); 19 | 20 | factor(); 21 | 22 | // more factoring? 23 | 24 | p1 = cdddr(p1); 25 | while (iscons(p1)) 26 | { 27 | push(car(p1)); 28 | eval(); 29 | factor_again(); 30 | p1 = cdr(p1); 31 | } 32 | } 33 | 34 | void 35 | factor_again(void) 36 | { 37 | int h, n; 38 | 39 | save(); 40 | 41 | p2 = pop(); 42 | p1 = pop(); 43 | 44 | h = tos; 45 | 46 | if (car(p1) == symbol(MULTIPLY)) 47 | { 48 | p1 = cdr(p1); 49 | while (iscons(p1)) 50 | { 51 | push(car(p1)); 52 | push(p2); 53 | factor_term(); 54 | p1 = cdr(p1); 55 | } 56 | } 57 | else 58 | { 59 | push(p1); 60 | push(p2); 61 | factor_term(); 62 | } 63 | 64 | n = tos - h; 65 | 66 | if (n > 1) 67 | multiply_all_noexpand(n); 68 | 69 | restore(); 70 | } 71 | 72 | void 73 | factor_term(void) 74 | { 75 | save(); 76 | factorpoly(); 77 | p1 = pop(); 78 | if (car(p1) == symbol(MULTIPLY)) 79 | { 80 | p1 = cdr(p1); 81 | while (iscons(p1)) 82 | { 83 | push(car(p1)); 84 | p1 = cdr(p1); 85 | } 86 | } 87 | else 88 | push(p1); 89 | restore(); 90 | } 91 | 92 | void 93 | factor(void) 94 | { 95 | save(); 96 | p2 = pop(); 97 | p1 = pop(); 98 | if (isinteger(p1)) 99 | { 100 | push(p1); 101 | factor_number(); // see pollard.cpp 102 | } 103 | else 104 | { 105 | push(p1); 106 | push(p2); 107 | factorpoly(); 108 | } 109 | restore(); 110 | } 111 | 112 | // for factoring small integers (2^32 or less) 113 | 114 | void 115 | factor_small_number(void) 116 | { 117 | int d, expo, i, n; 118 | 119 | save(); 120 | 121 | n = pop_integer(); 122 | 123 | if (n == (int)0x80000000) 124 | stop("number too big to factor"); 125 | 126 | if (n < 0) 127 | n = -n; 128 | 129 | for (i = 0; i < MAXPRIMETAB; i++) 130 | { 131 | 132 | d = primetab[i]; 133 | 134 | if (d > n / d) 135 | break; 136 | 137 | expo = 0; 138 | 139 | while (n % d == 0) 140 | { 141 | n /= d; 142 | expo++; 143 | } 144 | 145 | if (expo) 146 | { 147 | push_integer(d); 148 | push_integer(expo); 149 | } 150 | } 151 | 152 | if (n > 1) 153 | { 154 | push_integer(n); 155 | push_integer(1); 156 | } 157 | 158 | restore(); 159 | } 160 | 161 | #if SELFTEST 162 | 163 | static char *s[] = { 164 | 165 | "factor(0)", 166 | "0", 167 | 168 | "factor(1)", 169 | "1", 170 | 171 | "factor(2)", 172 | "2", 173 | 174 | "factor(3)", 175 | "3", 176 | 177 | "factor(4)", 178 | "2^2", 179 | 180 | "factor(5)", 181 | "5", 182 | 183 | "factor(6)", 184 | "2*3", 185 | 186 | "factor(7)", 187 | "7", 188 | 189 | "factor(8)", 190 | "2^3", 191 | 192 | "factor(9)", 193 | "3^2", 194 | 195 | "factor(10)", 196 | "2*5", 197 | 198 | "factor(100!)", 199 | "2^97*3^48*5^24*7^16*11^9*13^7*17^5*19^5*23^4*29^3*31^3*37^2*41^2*43^2*47^2*53*59*61*67*71*73*79*83*89*97", 200 | 201 | "factor(2*(2^30-35))", 202 | "2*1073741789", 203 | 204 | // x is the 10,000th prime 205 | 206 | // Prime factors greater than x^2 are found using the Pollard rho method 207 | 208 | "a=104729", 209 | "", 210 | 211 | "factor(2*(a^2+6))", 212 | "2*10968163447", 213 | 214 | "factor((a^2+6)^2)", 215 | "10968163447*10968163447", // FIXME should be 10968163447^2 216 | 217 | "factor((a^2+6)*(a^2+60))", 218 | "10968163501*10968163447", // FIXME sort order 219 | 220 | "f=(x+1)(x+2)(y+3)(y+4)", 221 | "", 222 | 223 | "factor(f,x,y)", 224 | "(x+1)*(x+2)*(y+3)*(y+4)", 225 | 226 | "factor(f,y,x)", 227 | "(x+1)*(x+2)*(y+3)*(y+4)", 228 | 229 | "f=(x+1)(x+1)(y+2)(y+2)", 230 | "", 231 | 232 | "factor(f,x,y)", 233 | "(x+1)^2*(y+2)^2", 234 | 235 | "factor(f,y,x)", 236 | "(x+1)^2*(y+2)^2", 237 | }; 238 | 239 | void 240 | test_factor_number(void) 241 | { 242 | test(__FILE__, s, sizeof s / sizeof (char *)); 243 | } 244 | 245 | #endif 246 | -------------------------------------------------------------------------------- /Eigenmath/Sources/factorial.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | extern void bignum_factorial(int); 5 | 6 | void 7 | factorial(void) 8 | { 9 | int n; 10 | save(); 11 | p1 = pop(); 12 | push(p1); 13 | n = pop_integer(); 14 | if (n < 0 || n == (int)0x80000000) 15 | { 16 | push_symbol(FACTORIAL); 17 | push(p1); 18 | list(2); 19 | restore(); 20 | return; 21 | } 22 | bignum_factorial(n); 23 | restore(); 24 | } 25 | 26 | void sfac_product(void); 27 | void sfac_product_f(U **, int, int); 28 | 29 | // simplification rules for factorials (m < n) 30 | // 31 | // (e + 1) * factorial(e) -> factorial(e + 1) 32 | // 33 | // factorial(e) / e -> factorial(e - 1) 34 | // 35 | // e / factorial(e) -> 1 / factorial(e - 1) 36 | // 37 | // factorial(e + n) 38 | // ---------------- -> (e + m + 1)(e + m + 2)...(e + n) 39 | // factorial(e + m) 40 | // 41 | // factorial(e + m) 1 42 | // ---------------- -> -------------------------------- 43 | // factorial(e + n) (e + m + 1)(e + m + 2)...(e + n) 44 | 45 | void 46 | simplifyfactorials(void) 47 | { 48 | int x; 49 | 50 | save(); 51 | 52 | x = expanding; 53 | expanding = 0; 54 | 55 | p1 = pop(); 56 | 57 | if (car(p1) == symbol(ADD)) 58 | { 59 | push(zero); 60 | p1 = cdr(p1); 61 | while (iscons(p1)) 62 | { 63 | push(car(p1)); 64 | simplifyfactorials(); 65 | add(); 66 | p1 = cdr(p1); 67 | } 68 | expanding = x; 69 | restore(); 70 | return; 71 | } 72 | 73 | if (car(p1) == symbol(MULTIPLY)) 74 | { 75 | sfac_product(); 76 | expanding = x; 77 | restore(); 78 | return; 79 | } 80 | 81 | push(p1); 82 | 83 | expanding = x; 84 | restore(); 85 | } 86 | 87 | void 88 | sfac_product(void) 89 | { 90 | int i, j, n; 91 | U **s; 92 | 93 | s = stack + tos; 94 | 95 | p1 = cdr(p1); 96 | n = 0; 97 | while (iscons(p1)) 98 | { 99 | push(car(p1)); 100 | p1 = cdr(p1); 101 | n++; 102 | } 103 | 104 | for (i = 0; i < n - 1; i++) 105 | { 106 | if (s[i] == symbol(NIL)) 107 | continue; 108 | for (j = i + 1; j < n; j++) 109 | { 110 | if (s[j] == symbol(NIL)) 111 | continue; 112 | sfac_product_f(s, i, j); 113 | } 114 | } 115 | 116 | push(one); 117 | 118 | for (i = 0; i < n; i++) 119 | { 120 | if (s[i] == symbol(NIL)) 121 | continue; 122 | push(s[i]); 123 | multiply(); 124 | } 125 | 126 | p1 = pop(); 127 | 128 | tos -= n; 129 | 130 | push(p1); 131 | } 132 | 133 | void 134 | sfac_product_f(U **s, int a, int b) 135 | { 136 | int i, n; 137 | 138 | p1 = s[a]; 139 | p2 = s[b]; 140 | 141 | if (ispower(p1)) 142 | { 143 | p3 = caddr(p1); 144 | p1 = cadr(p1); 145 | } 146 | else 147 | p3 = one; 148 | 149 | if (ispower(p2)) 150 | { 151 | p4 = caddr(p2); 152 | p2 = cadr(p2); 153 | } 154 | else 155 | p4 = one; 156 | 157 | if (isfactorial(p1) && isfactorial(p2)) 158 | { 159 | 160 | // Determine if the powers cancel. 161 | 162 | push(p3); 163 | push(p4); 164 | add(); 165 | yyexpand(); 166 | n = pop_integer(); 167 | if (n != 0) 168 | return; 169 | 170 | // Find the difference between the two factorial args. 171 | 172 | // For example, the difference between (a + 2)! and a! is 2. 173 | 174 | push(cadr(p1)); 175 | push(cadr(p2)); 176 | subtract(); 177 | yyexpand(); // to simplify 178 | 179 | n = pop_integer(); 180 | if (n == 0 || n == (int)0x80000000) 181 | return; 182 | if (n < 0) 183 | { 184 | n = -n; 185 | p5 = p1; 186 | p1 = p2; 187 | p2 = p5; 188 | p5 = p3; 189 | p3 = p4; 190 | p4 = p5; 191 | } 192 | 193 | push(one); 194 | 195 | for (i = 1; i <= n; i++) 196 | { 197 | push(cadr(p2)); 198 | push_integer(i); 199 | add(); 200 | push(p3); 201 | power(); 202 | multiply(); 203 | } 204 | s[a] = pop(); 205 | s[b] = symbol(NIL); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Eigenmath/Sources/factors.cpp: -------------------------------------------------------------------------------- 1 | // Push expression factors onto the stack. For example... 2 | // 3 | // Input 4 | // 5 | // 2 6 | // 3x + 2x + 1 7 | // 8 | // Output on stack 9 | // 10 | // [ 3 ] 11 | // [ x^2 ] 12 | // [ 2 ] 13 | // [ x ] 14 | // [ 1 ] 15 | // 16 | // but not necessarily in that order. Returns the number of factors. 17 | 18 | #include "../Headers/defs.h" 19 | 20 | // Local U *p is OK here because no functional path to garbage collector. 21 | 22 | int 23 | factors(U *p) 24 | { 25 | int h = tos; 26 | if (car(p) == symbol(ADD)) 27 | { 28 | p = cdr(p); 29 | while (iscons(p)) 30 | { 31 | push_term_factors(car(p)); 32 | p = cdr(p); 33 | } 34 | } 35 | else 36 | push_term_factors(p); 37 | return tos - h; 38 | } 39 | 40 | // Local U *p is OK here because no functional path to garbage collector. 41 | 42 | void 43 | push_term_factors(U *p) 44 | { 45 | if (car(p) == symbol(MULTIPLY)) 46 | { 47 | p = cdr(p); 48 | while (iscons(p)) 49 | { 50 | push(car(p)); 51 | p = cdr(p); 52 | } 53 | } 54 | else 55 | push(p); 56 | } 57 | -------------------------------------------------------------------------------- /Eigenmath/Sources/filter.cpp: -------------------------------------------------------------------------------- 1 | /* Remove terms that involve a given symbol or expression. For example... 2 | 3 | filter(x^2 + x + 1, x) => 1 4 | 5 | filter(x^2 + x + 1, x^2) => x + 1 6 | */ 7 | 8 | #include "../Headers/defs.h" 9 | 10 | void 11 | eval_filter(void) 12 | { 13 | p1 = cdr(p1); 14 | push(car(p1)); 15 | eval(); 16 | p1 = cdr(p1); 17 | while (iscons(p1)) 18 | { 19 | push(car(p1)); 20 | eval(); 21 | filter(); 22 | p1 = cdr(p1); 23 | } 24 | } 25 | 26 | /* For example... 27 | 28 | push(F) 29 | push(X) 30 | filter() 31 | F = pop() 32 | */ 33 | 34 | void 35 | filter(void) 36 | { 37 | save(); 38 | p2 = pop(); 39 | p1 = pop(); 40 | filter_main(); 41 | restore(); 42 | } 43 | 44 | void 45 | filter_main(void) 46 | { 47 | if (car(p1) == symbol(ADD)) 48 | filter_sum(); 49 | else if (istensor(p1)) 50 | filter_tensor(); 51 | else if (find(p1, p2)) 52 | push_integer(0); 53 | else 54 | push(p1); 55 | } 56 | 57 | void 58 | filter_sum(void) 59 | { 60 | push_integer(0); 61 | p1 = cdr(p1); 62 | while (iscons(p1)) 63 | { 64 | push(car(p1)); 65 | push(p2); 66 | filter(); 67 | add(); 68 | p1 = cdr(p1); 69 | } 70 | } 71 | 72 | void 73 | filter_tensor(void) 74 | { 75 | int i, n; 76 | n = p1->u.tensor->nelem; 77 | p3 = alloc_tensor(n); 78 | p3->u.tensor->ndim = p1->u.tensor->ndim; 79 | for (i = 0; i < p1->u.tensor->ndim; i++) 80 | p3->u.tensor->dim[i] = p1->u.tensor->dim[i]; 81 | for (i = 0; i < n; i++) 82 | { 83 | push(p1->u.tensor->elem[i]); 84 | push(p2); 85 | filter(); 86 | p3->u.tensor->elem[i] = pop(); 87 | } 88 | push(p3); 89 | } 90 | -------------------------------------------------------------------------------- /Eigenmath/Sources/find.cpp: -------------------------------------------------------------------------------- 1 | // returns 1 if expr p contains expr q, otherweise returns 0 2 | 3 | #include "../Headers/defs.h" 4 | 5 | int 6 | find(U *p, U *q) 7 | { 8 | int i; 9 | 10 | if (equal(p, q)) 11 | return 1; 12 | 13 | if (istensor(p)) 14 | { 15 | for (i = 0; i < p->u.tensor->nelem; i++) 16 | if (find(p->u.tensor->elem[i], q)) 17 | return 1; 18 | return 0; 19 | } 20 | 21 | while (iscons(p)) 22 | { 23 | if (find(car(p), q)) 24 | return 1; 25 | p = cdr(p); 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Eigenmath/Sources/float.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_float(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | yyfloat(); 10 | eval(); // normalize 11 | } 12 | 13 | void 14 | yyfloat(void) 15 | { 16 | int i, h; 17 | save(); 18 | p1 = pop(); 19 | if (iscons(p1)) 20 | { 21 | h = tos; 22 | while (iscons(p1)) 23 | { 24 | push(car(p1)); 25 | yyfloat(); 26 | p1 = cdr(p1); 27 | } 28 | list(tos - h); 29 | } 30 | else if (p1->k == TENSOR) 31 | { 32 | push(p1); 33 | copy_tensor(); 34 | p1 = pop(); 35 | for (i = 0; i < p1->u.tensor->nelem; i++) 36 | { 37 | push(p1->u.tensor->elem[i]); 38 | yyfloat(); 39 | p1->u.tensor->elem[i] = pop(); 40 | } 41 | push(p1); 42 | } 43 | else if (p1->k == NUM) 44 | { 45 | push(p1); 46 | bignum_float(); 47 | } 48 | else if (p1 == symbol(PI)) 49 | push_double(M_PI); 50 | else if (p1 == symbol(E)) 51 | push_double(M_E); 52 | else 53 | push(p1); 54 | restore(); 55 | } 56 | 57 | #if SELFTEST 58 | 59 | static char *s[] = { 60 | 61 | "float(x)", 62 | "x", 63 | 64 | "float(1/2)", 65 | "0.5", 66 | 67 | "float(pi)", 68 | "3.14159", 69 | 70 | "float(exp(1))", 71 | "2.71828", 72 | 73 | "x=(1/2,1/4)", 74 | "", 75 | 76 | "float(x)", 77 | "(0.5,0.25)", 78 | 79 | "x", 80 | "(1/2,1/4)", 81 | 82 | "x=quote(x)", 83 | "", 84 | }; 85 | 86 | void 87 | test_float(void) 88 | { 89 | test(__FILE__, s, sizeof s / sizeof (char *)); 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /Eigenmath/Sources/floor.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_floor(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | yfloor(); 10 | } 11 | 12 | void 13 | yfloor(void) 14 | { 15 | save(); 16 | yyfloor(); 17 | restore(); 18 | } 19 | 20 | void 21 | yyfloor(void) 22 | { 23 | double d; 24 | 25 | p1 = pop(); 26 | 27 | if (!isnum(p1)) 28 | { 29 | push_symbol(FLOOR); 30 | push(p1); 31 | list(2); 32 | return; 33 | } 34 | 35 | if (isdouble(p1)) 36 | { 37 | d = floor(p1->u.d); 38 | push_double(d); 39 | return; 40 | } 41 | 42 | if (isinteger(p1)) 43 | { 44 | push(p1); 45 | return; 46 | } 47 | 48 | p3 = alloc(); 49 | p3->k = NUM; 50 | p3->u.q.a = mdiv(p1->u.q.a, p1->u.q.b); 51 | p3->u.q.b = mint(1); 52 | push(p3); 53 | 54 | if (isnegativenumber(p1)) 55 | { 56 | push_integer(-1); 57 | add(); 58 | } 59 | } 60 | 61 | #if SELFTEST 62 | 63 | static char *s[] = { 64 | 65 | "floor(a)", 66 | "floor(a)", 67 | 68 | "floor(a+b)", 69 | "floor(a+b)", 70 | 71 | "floor(5/2)", 72 | "2", 73 | 74 | "floor(4/2)", 75 | "2", 76 | 77 | "floor(3/2)", 78 | "1", 79 | 80 | "floor(2/2)", 81 | "1", 82 | 83 | "floor(1/2)", 84 | "0", 85 | 86 | "floor(0/2)", 87 | "0", 88 | 89 | "floor(-1/2)", 90 | "-1", 91 | 92 | "floor(-2/2)", 93 | "-1", 94 | 95 | "floor(-3/2)", 96 | "-2", 97 | 98 | "floor(-4/2)", 99 | "-2", 100 | 101 | "floor(-5/2)", 102 | "-3", 103 | 104 | "floor(5/2.0)", 105 | "2", 106 | 107 | "floor(4/2.0)", 108 | "2", 109 | 110 | "floor(3/2.0)", 111 | "1", 112 | 113 | "floor(2/2.0)", 114 | "1", 115 | 116 | "floor(1/2.0)", 117 | "0", 118 | 119 | "floor(0.0)", 120 | "0", 121 | 122 | "floor(-1/2.0)", 123 | "-1", 124 | 125 | "floor(-2/2.0)", 126 | "-1", 127 | 128 | "floor(-3/2.0)", 129 | "-2", 130 | 131 | "floor(-4/2.0)", 132 | "-2", 133 | 134 | "floor(-5/2.0)", 135 | "-3", 136 | }; 137 | 138 | void 139 | test_floor(void) 140 | { 141 | test(__FILE__, s, sizeof s / sizeof (char *)); 142 | } 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /Eigenmath/Sources/for.cpp: -------------------------------------------------------------------------------- 1 | // 'for' function 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define A p3 6 | #define B p4 7 | #define I p5 8 | #define X p6 9 | 10 | void 11 | eval_for(void) 12 | { 13 | int i, j, k; 14 | 15 | // 1st arg (quoted) 16 | 17 | X = cadr(p1); 18 | if (!issymbol(X)) 19 | stop("for: 1st arg?"); 20 | 21 | // 2nd arg 22 | 23 | push(caddr(p1)); 24 | eval(); 25 | j = pop_integer(); 26 | if (j == (int)0x80000000) 27 | stop("for: 2nd arg?"); 28 | 29 | // 3rd arg 30 | 31 | push(cadddr(p1)); 32 | eval(); 33 | k = pop_integer(); 34 | if (k == (int)0x80000000) 35 | stop("for: 3rd arg?"); 36 | 37 | // remaining args 38 | 39 | p1 = cddddr(p1); 40 | 41 | B = get_binding(X); 42 | A = get_arglist(X); 43 | 44 | for (i = j; i <= k; i++) 45 | { 46 | push_integer(i); 47 | I = pop(); 48 | set_binding(X, I); 49 | p2 = p1; 50 | while (iscons(p2)) 51 | { 52 | push(car(p2)); 53 | eval(); 54 | pop(); 55 | p2 = cdr(p2); 56 | } 57 | } 58 | 59 | set_binding_and_arglist(X, B, A); 60 | 61 | // return value 62 | 63 | push_symbol(NIL); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Eigenmath/Sources/gamma.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Author : philippe.billet@noos.fr 4 | // 5 | // Gamma function gamma(x) 6 | // 7 | //----------------------------------------------------------------------------- 8 | 9 | #include "../Headers/defs.h" 10 | 11 | void gamma(void); 12 | static void gammaf(void); 13 | static void gamma_of_sum(void); 14 | 15 | void 16 | eval_gamma(void) 17 | { 18 | push(cadr(p1)); 19 | eval(); 20 | gamma(); 21 | } 22 | 23 | void 24 | gamma(void) 25 | { 26 | save(); 27 | gammaf(); 28 | restore(); 29 | } 30 | 31 | static void 32 | gammaf(void) 33 | { 34 | // double d; 35 | 36 | p1 = pop(); 37 | 38 | if (isrational(p1) && MEQUAL(p1->u.q.a, 1) && MEQUAL(p1->u.q.b, 2)) 39 | { 40 | push_symbol(PI);; 41 | push_rational(1, 2); 42 | power(); 43 | return; 44 | } 45 | 46 | if (isrational(p1) && MEQUAL(p1->u.q.a, 3) && MEQUAL(p1->u.q.b, 2)) 47 | { 48 | push_symbol(PI);; 49 | push_rational(1, 2); 50 | power(); 51 | push_rational(1, 2); 52 | multiply(); 53 | return; 54 | } 55 | 56 | // if (p1->k == DOUBLE) { 57 | // d = exp(lgamma(p1->u.d)); 58 | // push_double(d); 59 | // return; 60 | // } 61 | 62 | if (isnegativeterm(p1)) 63 | { 64 | push_symbol(PI); 65 | push_integer(-1); 66 | multiply(); 67 | push_symbol(PI); 68 | push(p1); 69 | multiply(); 70 | sine(); 71 | push(p1); 72 | multiply(); 73 | push(p1); 74 | negate(); 75 | gamma(); 76 | multiply(); 77 | divide(); 78 | return; 79 | } 80 | 81 | if (car(p1) == symbol(ADD)) 82 | { 83 | gamma_of_sum(); 84 | return; 85 | } 86 | 87 | push_symbol(GAMMA); 88 | push(p1); 89 | list(2); 90 | return; 91 | } 92 | 93 | static void 94 | gamma_of_sum(void) 95 | { 96 | p3 = cdr(p1); 97 | if (isrational(car(p3)) && MEQUAL(car(p3)->u.q.a, 1) && MEQUAL(car(p3)->u.q.b, 1)) 98 | { 99 | push(cadr(p3)); 100 | push(cadr(p3)); 101 | gamma(); 102 | multiply(); 103 | } 104 | else 105 | { 106 | if (isrational(car(p3)) && MEQUAL(car(p3)->u.q.a, -1) && MEQUAL(car(p3)->u.q.b, 1)) 107 | { 108 | push(cadr(p3)); 109 | gamma(); 110 | push(cadr(p3)); 111 | push_integer(-1); 112 | add(); 113 | divide(); 114 | } 115 | else 116 | { 117 | push_symbol(GAMMA); 118 | push(p1); 119 | list(2); 120 | return; 121 | } 122 | } 123 | } 124 | 125 | #if SELFTEST 126 | 127 | static char *s[] = { 128 | 129 | "Gamma(a)", 130 | "Gamma(a)", 131 | 132 | // "float(gamma(10))", 133 | // "362880", 134 | 135 | "Gamma(x+1)", 136 | "x*Gamma(x)", 137 | 138 | "Gamma(1/2)", 139 | "pi^(1/2)", 140 | 141 | "Gamma(x-1)-Gamma(x)/(-1+x)", 142 | "0", 143 | 144 | "Gamma(-x)", 145 | "-pi/(x*Gamma(x)*sin(pi*x))", 146 | 147 | }; 148 | 149 | void 150 | test_gamma(void) 151 | { 152 | test(__FILE__, s, sizeof s / sizeof (char *)); 153 | } 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /Eigenmath/Sources/guess.cpp: -------------------------------------------------------------------------------- 1 | // Guess which symbol to use for derivative, integral, etc. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | guess(void) 7 | { 8 | U *p; 9 | p = pop(); 10 | push(p); 11 | if (find(p, symbol(SYMBOL_X))) 12 | push_symbol(SYMBOL_X); 13 | else if (find(p, symbol(SYMBOL_Y))) 14 | push_symbol(SYMBOL_Y); 15 | else if (find(p, symbol(SYMBOL_Z))) 16 | push_symbol(SYMBOL_Z); 17 | else if (find(p, symbol(SYMBOL_T))) 18 | push_symbol(SYMBOL_T); 19 | else if (find(p, symbol(SYMBOL_S))) 20 | push_symbol(SYMBOL_S); 21 | else 22 | push_symbol(SYMBOL_X); 23 | } 24 | -------------------------------------------------------------------------------- /Eigenmath/Sources/hermite.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Hermite polynomial 4 | // 5 | // Input: tos-2 x (can be a symbol or expr) 6 | // 7 | // tos-1 n 8 | // 9 | // Output: Result on stack 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "../Headers/defs.h" 14 | 15 | void 16 | hermite(void) 17 | { 18 | save(); 19 | yyhermite(); 20 | restore(); 21 | } 22 | 23 | // uses the recurrence relation H(x,n+1)=2*x*H(x,n)-2*n*H(x,n-1) 24 | 25 | #define X p1 26 | #define N p2 27 | #define Y p3 28 | #define Y1 p4 29 | #define Y0 p5 30 | 31 | void 32 | yyhermite(void) 33 | { 34 | int n; 35 | 36 | N = pop(); 37 | X = pop(); 38 | 39 | push(N); 40 | n = pop_integer(); 41 | 42 | if (n < 0) 43 | { 44 | push_symbol(HERMITE); 45 | push(X); 46 | push(N); 47 | list(3); 48 | return; 49 | } 50 | 51 | if (issymbol(X)) 52 | yyhermite2(n); 53 | else 54 | { 55 | Y = X; // do this when X is an expr 56 | X = symbol(SECRETX); 57 | yyhermite2(n); 58 | X = Y; 59 | push(symbol(SECRETX)); 60 | push(X); 61 | subst(); 62 | eval(); 63 | } 64 | } 65 | 66 | void 67 | yyhermite2(int n) 68 | { 69 | int i; 70 | 71 | push_integer(1); 72 | push_integer(0); 73 | 74 | Y1 = pop(); 75 | 76 | for (i = 0; i < n; i++) 77 | { 78 | 79 | Y0 = Y1; 80 | 81 | Y1 = pop(); 82 | 83 | push(X); 84 | push(Y1); 85 | multiply(); 86 | 87 | push_integer(i); 88 | push(Y0); 89 | multiply(); 90 | 91 | subtract(); 92 | 93 | push_integer(2); 94 | multiply(); 95 | } 96 | } 97 | 98 | #if SELFTEST 99 | 100 | static char *s[] = { 101 | 102 | "hermite(x,n)", 103 | "hermite(x,n)", 104 | 105 | "hermite(x,0)-1", 106 | "0", 107 | 108 | "hermite(x,1)-2*x", 109 | "0", 110 | 111 | "hermite(x,2)-(4*x^2-2)", 112 | "0", 113 | 114 | "hermite(x,3)-(8*x^3-12*x)", 115 | "0", 116 | 117 | "hermite(x,4)-(16*x^4-48*x^2+12)", 118 | "0", 119 | 120 | "hermite(x,5)-(32*x^5-160*x^3+120*x)", 121 | "0", 122 | 123 | "hermite(x,6)-(64*x^6-480*x^4+720*x^2-120)", 124 | "0", 125 | 126 | "hermite(x,7)-(128*x^7-1344*x^5+3360*x^3-1680*x)", 127 | "0", 128 | 129 | "hermite(x,8)-(256*x^8-3584*x^6+13440*x^4-13440*x^2+1680)", 130 | "0", 131 | 132 | "hermite(x,9)-(512*x^9-9216*x^7+48384*x^5-80640*x^3+30240*x)", 133 | "0", 134 | 135 | "hermite(x,10)-(1024*x^10-23040*x^8+161280*x^6-403200*x^4+302400*x^2-30240)", 136 | "0", 137 | 138 | "hermite(a-b,10)-eval(subst(a-b,x,hermite(x,10)))", 139 | "0", 140 | }; 141 | 142 | void 143 | test_hermite(void) 144 | { 145 | test(__FILE__, s, sizeof s / sizeof (char *)); 146 | } 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /Eigenmath/Sources/hilbert.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | //----------------------------------------------------------------------------- 4 | // 5 | // Create a Hilbert matrix 6 | // 7 | // Input: Dimension on stack 8 | // 9 | // Output: Hilbert matrix on stack 10 | // 11 | // Example: 12 | // 13 | // > hilbert(5) 14 | // ((1,1/2,1/3,1/4),(1/2,1/3,1/4,1/5),(1/3,1/4,1/5,1/6),(1/4,1/5,1/6,1/7)) 15 | // 16 | //----------------------------------------------------------------------------- 17 | 18 | #include "../Headers/defs.h" 19 | 20 | #define A p1 21 | #define N p2 22 | 23 | #define AELEM(i, j) A->u.tensor->elem[i * n + j] 24 | 25 | void 26 | hilbert(void) 27 | { 28 | int i, j, n; 29 | save(); 30 | N = pop(); 31 | push(N); 32 | n = pop_integer(); 33 | if (n < 2) 34 | { 35 | push_symbol(HILBERT); 36 | push(N); 37 | list(2); 38 | restore(); 39 | return; 40 | } 41 | push_zero_matrix(n, n); 42 | A = pop(); 43 | for (i = 0; i < n; i++) 44 | { 45 | for (j = 0; j < n; j++) 46 | { 47 | push_integer(i + j + 1); 48 | inverse(); 49 | AELEM(i, j) = pop(); 50 | } 51 | } 52 | push(A); 53 | restore(); 54 | } 55 | -------------------------------------------------------------------------------- /Eigenmath/Sources/imag.cpp: -------------------------------------------------------------------------------- 1 | /* Returns the coefficient of the imaginary part of complex z 2 | 3 | z imag(z) 4 | - ------- 5 | 6 | a + i b b 7 | 8 | exp(i a) sin(a) 9 | */ 10 | 11 | #include "../Headers/defs.h" 12 | 13 | void 14 | eval_imag(void) 15 | { 16 | push(cadr(p1)); 17 | eval(); 18 | imag(); 19 | } 20 | 21 | void 22 | imag(void) 23 | { 24 | save(); 25 | rect(); 26 | p1 = pop(); 27 | push(p1); 28 | push(p1); 29 | conjugate(); 30 | subtract(); 31 | push_integer(2); 32 | divide(); 33 | push(imaginaryunit); 34 | divide(); 35 | restore(); 36 | } 37 | 38 | #if SELFTEST 39 | 40 | static char *s[] = { 41 | 42 | "imag(a+i*b)", 43 | "b", 44 | 45 | "imag(1+exp(i*pi/3))", 46 | "1/2*3^(1/2)", 47 | 48 | "imag(i)", 49 | "1", 50 | 51 | "imag((-1)^(1/3))", 52 | "1/2*3^(1/2)", 53 | 54 | "imag(-i)", 55 | "-1", 56 | }; 57 | 58 | void 59 | test_imag(void) 60 | { 61 | test(__FILE__, s, sizeof s / sizeof (char *)); 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Eigenmath/Sources/integral.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | #define F p3 5 | #define X p4 6 | #define N p5 7 | 8 | void 9 | eval_integral(void) 10 | { 11 | int i, n; 12 | 13 | // evaluate 1st arg to get function F 14 | 15 | p1 = cdr(p1); 16 | push(car(p1)); 17 | eval(); 18 | 19 | // evaluate 2nd arg and then... 20 | 21 | // example result of 2nd arg what to do 22 | // 23 | // integral(f) nil guess X, N = nil 24 | // integral(f,2) 2 guess X, N = 2 25 | // integral(f,x) x X = x, N = nil 26 | // integral(f,x,2) x X = x, N = 2 27 | // integral(f,x,y) x X = x, N = y 28 | 29 | p1 = cdr(p1); 30 | push(car(p1)); 31 | eval(); 32 | 33 | p2 = pop(); 34 | if (p2 == symbol(NIL)) 35 | { 36 | guess(); 37 | push(symbol(NIL)); 38 | } 39 | else if (isnum(p2)) 40 | { 41 | guess(); 42 | push(p2); 43 | } 44 | else 45 | { 46 | push(p2); 47 | p1 = cdr(p1); 48 | push(car(p1)); 49 | eval(); 50 | } 51 | 52 | N = pop(); 53 | X = pop(); 54 | F = pop(); 55 | 56 | while (1) 57 | { 58 | 59 | // N might be a symbol instead of a number 60 | 61 | if (isnum(N)) 62 | { 63 | push(N); 64 | n = pop_integer(); 65 | if (n == (int)0x80000000) 66 | stop("nth integral: check n"); 67 | } 68 | else 69 | n = 1; 70 | 71 | push(F); 72 | 73 | if (n >= 0) 74 | { 75 | for (i = 0; i < n; i++) 76 | { 77 | push(X); 78 | integral(); 79 | } 80 | } 81 | else 82 | { 83 | n = -n; 84 | for (i = 0; i < n; i++) 85 | { 86 | push(X); 87 | derivative(); 88 | } 89 | } 90 | 91 | F = pop(); 92 | 93 | // if N is nil then arglist is exhausted 94 | 95 | if (N == symbol(NIL)) 96 | break; 97 | 98 | // otherwise... 99 | 100 | // N arg1 what to do 101 | // 102 | // number nil break 103 | // number number N = arg1, continue 104 | // number symbol X = arg1, N = arg2, continue 105 | // 106 | // symbol nil X = N, N = nil, continue 107 | // symbol number X = N, N = arg1, continue 108 | // symbol symbol X = N, N = arg1, continue 109 | 110 | if (isnum(N)) 111 | { 112 | p1 = cdr(p1); 113 | push(car(p1)); 114 | eval(); 115 | N = pop(); 116 | if (N == symbol(NIL)) 117 | break; // arglist exhausted 118 | if (isnum(N)); // N = arg1 119 | else 120 | { 121 | X = N; // X = arg1 122 | p1 = cdr(p1); 123 | push(car(p1)); 124 | eval(); 125 | N = pop(); // N = arg2 126 | } 127 | } 128 | else 129 | { 130 | X = N; // X = N 131 | p1 = cdr(p1); 132 | push(car(p1)); 133 | eval(); 134 | N = pop(); // N = arg1 135 | } 136 | } 137 | 138 | push(F); // final result 139 | } 140 | 141 | void 142 | integral(void) 143 | { 144 | save(); 145 | p2 = pop(); 146 | p1 = pop(); 147 | if (car(p1) == symbol(ADD)) 148 | integral_of_sum(); 149 | else if (car(p1) == symbol(MULTIPLY)) 150 | integral_of_product(); 151 | else 152 | integral_of_form(); 153 | p1 = pop(); 154 | if (find(p1, symbol(INTEGRAL))) 155 | stop("integral: sorry, could not find a solution"); 156 | push(p1); 157 | simplify(); // polish the result 158 | eval(); // normalize the result 159 | restore(); 160 | } 161 | 162 | void 163 | integral_of_sum(void) 164 | { 165 | p1 = cdr(p1); 166 | push(car(p1)); 167 | push(p2); 168 | integral(); 169 | p1 = cdr(p1); 170 | while (iscons(p1)) 171 | { 172 | push(car(p1)); 173 | push(p2); 174 | integral(); 175 | add(); 176 | p1 = cdr(p1); 177 | } 178 | } 179 | 180 | void 181 | integral_of_product(void) 182 | { 183 | push(p1); 184 | push(p2); 185 | partition(); 186 | p1 = pop(); // pop variable part 187 | integral_of_form(); 188 | multiply(); // multiply constant part 189 | } 190 | 191 | extern char *itab[]; 192 | 193 | void 194 | integral_of_form(void) 195 | { 196 | push(p1); 197 | push(p2); 198 | transform(itab); 199 | p3 = pop(); 200 | if (p3 == symbol(NIL)) 201 | { 202 | push_symbol(INTEGRAL); 203 | push(p1); 204 | push(p2); 205 | list(3); 206 | } 207 | else 208 | push(p3); 209 | } 210 | -------------------------------------------------------------------------------- /Eigenmath/Sources/isprime.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_isprime(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | p1 = pop(); 10 | if (isnonnegativeinteger(p1) && mprime(p1->u.q.a)) 11 | push_integer(1); 12 | else 13 | push_integer(0); 14 | } 15 | 16 | #if SELFTEST 17 | 18 | static char *s[] = { 19 | 20 | // 0 and 1 are not prime numbers 21 | 22 | "isprime(0)", 23 | "0", 24 | 25 | "isprime(1)", 26 | "0", 27 | 28 | "isprime(13)", 29 | "1", 30 | 31 | "isprime(14)", 32 | "0", 33 | 34 | // from the Prime Curios web page 35 | 36 | "isprime(9007199254740991)", 37 | "0", 38 | 39 | // The largest prime that JavaScript supports 40 | 41 | "isprime(2^53 - 111)", 42 | "1", 43 | 44 | // misc. primes 45 | 46 | "isprime(2^50-71)", 47 | "1", 48 | 49 | "isprime(2^40-87)", 50 | "1", 51 | }; 52 | 53 | void 54 | test_isprime(void) 55 | { 56 | test(__FILE__, s, sizeof s / sizeof (char *)); 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /Eigenmath/Sources/laguerre.cpp: -------------------------------------------------------------------------------- 1 | /* Laguerre function 2 | 3 | Example 4 | 5 | laguerre(x,3) 6 | 7 | Result 8 | 9 | 1 3 3 2 10 | - --- x + --- x - 3 x + 1 11 | 6 2 12 | 13 | The computation uses the following recurrence relation. 14 | 15 | L(x,0,k) = 1 16 | 17 | L(x,1,k) = -x + k + 1 18 | 19 | n*L(x,n,k) = (2*(n-1)+1-x+k)*L(x,n-1,k) - (n-1+k)*L(x,n-2,k) 20 | 21 | In the "for" loop i = n-1 so the recurrence relation becomes 22 | 23 | (i+1)*L(x,n,k) = (2*i+1-x+k)*L(x,n-1,k) - (i+k)*L(x,n-2,k) 24 | */ 25 | 26 | #include "../Headers/defs.h" 27 | 28 | void 29 | eval_laguerre(void) 30 | { 31 | // 1st arg 32 | 33 | push(cadr(p1)); 34 | eval(); 35 | 36 | // 2nd arg 37 | 38 | push(caddr(p1)); 39 | eval(); 40 | 41 | // 3rd arg 42 | 43 | push(cadddr(p1)); 44 | eval(); 45 | 46 | p2 = pop(); 47 | if (p2 == symbol(NIL)) 48 | push_integer(0); 49 | else 50 | push(p2); 51 | 52 | laguerre(); 53 | } 54 | 55 | #define X p1 56 | #define N p2 57 | #define K p3 58 | #define Y p4 59 | #define Y0 p5 60 | #define Y1 p6 61 | 62 | void 63 | laguerre(void) 64 | { 65 | int n; 66 | save(); 67 | 68 | K = pop(); 69 | N = pop(); 70 | X = pop(); 71 | 72 | push(N); 73 | n = pop_integer(); 74 | 75 | if (n < 0) 76 | { 77 | push_symbol(LAGUERRE); 78 | push(X); 79 | push(N); 80 | push(K); 81 | list(4); 82 | restore(); 83 | return; 84 | } 85 | 86 | if (issymbol(X)) 87 | laguerre2(n); 88 | else 89 | { 90 | Y = X; // do this when X is an expr 91 | X = symbol(SECRETX); 92 | laguerre2(n); 93 | X = Y; 94 | push(symbol(SECRETX)); 95 | push(X); 96 | subst(); 97 | eval(); 98 | } 99 | 100 | restore(); 101 | } 102 | 103 | void 104 | laguerre2(int n) 105 | { 106 | int i; 107 | 108 | push_integer(1); 109 | push_integer(0); 110 | 111 | Y1 = pop(); 112 | 113 | for (i = 0; i < n; i++) 114 | { 115 | 116 | Y0 = Y1; 117 | 118 | Y1 = pop(); 119 | 120 | push_integer(2 * i + 1); 121 | push(X); 122 | subtract(); 123 | push(K); 124 | add(); 125 | push(Y1); 126 | multiply(); 127 | 128 | push_integer(i); 129 | push(K); 130 | add(); 131 | push(Y0); 132 | multiply(); 133 | 134 | subtract(); 135 | 136 | push_integer(i + 1); 137 | divide(); 138 | } 139 | } 140 | 141 | #if SELFTEST 142 | 143 | static char *s[] = { 144 | 145 | "laguerre(x,n)", 146 | "laguerre(x,n,0)", 147 | 148 | "laguerre(x,n,k)", 149 | "laguerre(x,n,k)", 150 | 151 | "laguerre(x,0)-1", 152 | "0", 153 | 154 | "laguerre(x,1)-(-x+1)", 155 | "0", 156 | 157 | "laguerre(x,2)-1/2*(x^2-4*x+2)", 158 | "0", 159 | 160 | "laguerre(x,3)-1/6*(-x^3+9*x^2-18*x+6)", 161 | "0", 162 | 163 | "laguerre(x,0,k)-1", 164 | "0", 165 | 166 | "laguerre(x,1,k)-(-x+k+1)", 167 | "0", 168 | 169 | "laguerre(x,2,k)-1/2*(x^2-2*(k+2)*x+(k+1)*(k+2))", 170 | "0", 171 | 172 | "laguerre(x,3,k)-1/6*(-x^3+3*(k+3)*x^2-3*(k+2)*(k+3)*x+(k+1)*(k+2)*(k+3))", 173 | "0", 174 | 175 | "laguerre(a-b,10)-eval(subst(a-b,x,laguerre(x,10)))", 176 | "0", 177 | }; 178 | 179 | void 180 | test_laguerre(void) 181 | { 182 | test(__FILE__, s, sizeof s / sizeof (char *)); 183 | } 184 | 185 | #endif 186 | -------------------------------------------------------------------------------- /Eigenmath/Sources/laplace.cpp: -------------------------------------------------------------------------------- 1 | // Laplace transform 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_laplace(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | push(symbol(SYMBOL_T)); 11 | laplace(); 12 | } 13 | 14 | #define F p3 15 | #define T p4 16 | #define A p5 17 | 18 | void 19 | laplace(void) 20 | { 21 | int h; 22 | save(); 23 | 24 | T = pop(); 25 | F = pop(); 26 | 27 | // L[f + g] = L[f] + L[g] 28 | 29 | if (car(F) == symbol(ADD)) 30 | { 31 | p1 = cdr(F); 32 | h = tos; 33 | while (iscons(p1)) 34 | { 35 | push(car(p1)); 36 | push(T); 37 | laplace(); 38 | p1 = cdr(p1); 39 | } 40 | add_all(tos - h); 41 | restore(); 42 | return; 43 | } 44 | 45 | // L[Af] = A L[f] 46 | 47 | if (car(F) == symbol(MULTIPLY)) 48 | { 49 | push(F); 50 | push(T); 51 | partition(); 52 | F = pop(); 53 | A = pop(); 54 | laplace_main(); 55 | push(A); 56 | multiply(); 57 | } 58 | else 59 | laplace_main(); 60 | 61 | restore(); 62 | } 63 | 64 | void 65 | laplace_main(void) 66 | { 67 | int n; 68 | 69 | // L[t] = 1 / s^2 70 | 71 | if (F == symbol(SYMBOL_T)) 72 | { 73 | push_symbol(SYMBOL_S); 74 | push_integer(-2); 75 | power(); 76 | return; 77 | } 78 | 79 | // L[t^n] = n! / s^(n+1) 80 | 81 | if (car(F) == symbol(POWER) && cadr(F) == T) 82 | { 83 | push(caddr(F)); 84 | n = pop_integer(); 85 | if (n > 0) 86 | { 87 | push_integer(n); 88 | factorial(); 89 | push_symbol(SYMBOL_S); 90 | push_integer(n + 1); 91 | power(); 92 | divide(); 93 | return; 94 | } 95 | } 96 | 97 | stop("laplace: cannot solve"); 98 | } 99 | 100 | #if SELFTEST 101 | 102 | static char *s[] = { 103 | 104 | // float ok? 105 | 106 | "laplace(3t^2.0)", 107 | "6/(s^3)", 108 | }; 109 | 110 | void 111 | test_laplace(void) 112 | { 113 | test(__FILE__, s, sizeof s / sizeof (char *)); 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /Eigenmath/Sources/lcm.cpp: -------------------------------------------------------------------------------- 1 | // Find the least common multiple of two expressions. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_lcm(void) 7 | { 8 | p1 = cdr(p1); 9 | push(car(p1)); 10 | eval(); 11 | p1 = cdr(p1); 12 | while (iscons(p1)) 13 | { 14 | push(car(p1)); 15 | eval(); 16 | lcm(); 17 | p1 = cdr(p1); 18 | } 19 | } 20 | 21 | void 22 | lcm(void) 23 | { 24 | int x; 25 | x = expanding; 26 | save(); 27 | yylcm(); 28 | restore(); 29 | expanding = x; 30 | } 31 | 32 | void 33 | yylcm(void) 34 | { 35 | expanding = 1; 36 | 37 | p2 = pop(); 38 | p1 = pop(); 39 | 40 | push(p1); 41 | push(p2); 42 | gcd(); 43 | 44 | push(p1); 45 | divide(); 46 | 47 | push(p2); 48 | divide(); 49 | 50 | inverse(); 51 | } 52 | 53 | #if SELFTEST 54 | 55 | static char *s[] = { 56 | 57 | "lcm(4,6)", 58 | "12", 59 | 60 | "lcm(4*x,6*x*y)", 61 | "12*x*y", 62 | 63 | // multiple arguments 64 | 65 | "lcm(2,3,4)", 66 | "12", 67 | }; 68 | 69 | void 70 | test_lcm(void) 71 | { 72 | test(__FILE__, s, sizeof (s) / sizeof (char *)); 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /Eigenmath/Sources/leading.cpp: -------------------------------------------------------------------------------- 1 | /* Return the leading coefficient of a polynomial. 2 | 3 | Example 4 | 5 | leading(5x^2+x+1,x) 6 | 7 | Result 8 | 9 | 5 10 | 11 | The result is undefined if P is not a polynomial. */ 12 | 13 | #include "../Headers/defs.h" 14 | 15 | void 16 | eval_leading(void) 17 | { 18 | push(cadr(p1)); 19 | eval(); 20 | push(caddr(p1)); 21 | eval(); 22 | p1 = pop(); 23 | if (p1 == symbol(NIL)) 24 | guess(); 25 | else 26 | push(p1); 27 | leading(); 28 | } 29 | 30 | #define P p1 31 | #define X p2 32 | #define N p3 33 | 34 | void 35 | leading(void) 36 | { 37 | save(); 38 | 39 | X = pop(); 40 | P = pop(); 41 | 42 | push(P); // N = degree of P 43 | push(X); 44 | degree(); 45 | N = pop(); 46 | 47 | push(P); // divide through by X ^ N 48 | push(X); 49 | push(N); 50 | power(); 51 | divide(); 52 | 53 | push(X); // remove terms that depend on X 54 | filter(); 55 | 56 | restore(); 57 | } 58 | -------------------------------------------------------------------------------- /Eigenmath/Sources/list.cpp: -------------------------------------------------------------------------------- 1 | // Create a list from n things on the stack. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | list(int n) 7 | { 8 | int i; 9 | push(symbol(NIL)); 10 | for (i = 0; i < n; i++) 11 | cons(); 12 | } 13 | -------------------------------------------------------------------------------- /Eigenmath/Sources/log.cpp: -------------------------------------------------------------------------------- 1 | // natural logarithm 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_log(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | logarithm(); 11 | } 12 | 13 | void 14 | logarithm(void) 15 | { 16 | save(); 17 | yylog(); 18 | restore(); 19 | } 20 | 21 | void 22 | yylog(void) 23 | { 24 | double d; 25 | 26 | p1 = pop(); 27 | 28 | if (p1 == symbol(E)) 29 | { 30 | push_integer(1); 31 | return; 32 | } 33 | 34 | if (equaln(p1, 1)) 35 | { 36 | push_integer(0); 37 | return; 38 | } 39 | 40 | if (isnegativenumber(p1)) 41 | { 42 | push(p1); 43 | negate(); 44 | logarithm(); 45 | push(imaginaryunit); 46 | push_symbol(PI); 47 | multiply(); 48 | add(); 49 | return; 50 | } 51 | 52 | if (isdouble(p1)) 53 | { 54 | d = log(p1->u.d); 55 | push_double(d); 56 | return; 57 | } 58 | 59 | // rational number and not an integer? 60 | 61 | if (isfraction(p1)) 62 | { 63 | push(p1); 64 | numerator(); 65 | logarithm(); 66 | push(p1); 67 | denominator(); 68 | logarithm(); 69 | subtract(); 70 | return; 71 | } 72 | 73 | // log(a ^ b) --> b log(a) 74 | 75 | if (car(p1) == symbol(POWER)) 76 | { 77 | push(caddr(p1)); 78 | push(cadr(p1)); 79 | logarithm(); 80 | multiply(); 81 | return; 82 | } 83 | 84 | // log(a * b) --> log(a) + log(b) 85 | 86 | if (car(p1) == symbol(MULTIPLY)) 87 | { 88 | push_integer(0); 89 | p1 = cdr(p1); 90 | while (iscons(p1)) 91 | { 92 | push(car(p1)); 93 | logarithm(); 94 | add(); 95 | p1 = cdr(p1); 96 | } 97 | return; 98 | } 99 | 100 | push_symbol(LOG); 101 | push(p1); 102 | list(2); 103 | } 104 | 105 | #if SELFTEST 106 | 107 | static char *s[] = { 108 | 109 | "log(1)", 110 | "0", 111 | 112 | "log(exp(1))", 113 | "1", 114 | 115 | "log(exp(x))", 116 | "x", 117 | 118 | "exp(log(x))", 119 | "x", 120 | 121 | "log(x^2)", 122 | "2*log(x)", 123 | 124 | "log(1/x)", 125 | "-log(x)", 126 | 127 | "log(a^b)", 128 | "b*log(a)", 129 | 130 | "log(2)", 131 | "log(2)", 132 | 133 | "log(2.0)", 134 | "0.693147", 135 | 136 | "float(log(2))", 137 | "0.693147", 138 | 139 | "log(a*b)", 140 | "log(a)+log(b)", 141 | 142 | "log(1/3)+log(3)", 143 | "0", 144 | 145 | "log(-1)", 146 | "i*pi", 147 | 148 | "log(-1.0)", 149 | "i*pi", 150 | }; 151 | 152 | void 153 | test_log(void) 154 | { 155 | test(__FILE__, s, sizeof s / sizeof (char *)); 156 | } 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mag.cpp: -------------------------------------------------------------------------------- 1 | /* Magnitude of complex z 2 | 3 | z mag(z) 4 | - ------ 5 | 6 | a a 7 | 8 | -a a 9 | 10 | (-1)^a 1 11 | 12 | exp(a + i b) exp(a) 13 | 14 | a b mag(a) mag(b) 15 | 16 | a + i b sqrt(a^2 + b^2) 17 | 18 | Notes 19 | 20 | 1. Handles mixed polar and rectangular forms, e.g. 1 + exp(i pi/3) 21 | 22 | 2. jean-francois.debroux reports that when z=(a+i*b)/(c+i*d) then 23 | 24 | mag(numerator(z)) / mag(denominator(z)) 25 | 26 | must be used to get the correct answer. Now the operation is 27 | automatic. 28 | */ 29 | 30 | #include "../Headers/defs.h" 31 | 32 | void 33 | eval_mag(void) 34 | { 35 | push(cadr(p1)); 36 | eval(); 37 | mag(); 38 | } 39 | 40 | void 41 | mag(void) 42 | { 43 | save(); 44 | p1 = pop(); 45 | push(p1); 46 | numerator(); 47 | yymag(); 48 | push(p1); 49 | denominator(); 50 | yymag(); 51 | divide(); 52 | restore(); 53 | } 54 | 55 | void 56 | yymag(void) 57 | { 58 | save(); 59 | p1 = pop(); 60 | if (isnegativenumber(p1)) 61 | { 62 | push(p1); 63 | negate(); 64 | } 65 | else if (car(p1) == symbol(POWER) && equaln(cadr(p1), -1)) 66 | // -1 to a power 67 | push_integer(1); 68 | else if (car(p1) == symbol(POWER) && cadr(p1) == symbol(E)) 69 | { 70 | // exponential 71 | push(caddr(p1)); 72 | real(); 73 | exponential(); 74 | } 75 | else if (car(p1) == symbol(MULTIPLY)) 76 | { 77 | // product 78 | push_integer(1); 79 | p1 = cdr(p1); 80 | while (iscons(p1)) 81 | { 82 | push(car(p1)); 83 | mag(); 84 | multiply(); 85 | p1 = cdr(p1); 86 | } 87 | } 88 | else if (car(p1) == symbol(ADD)) 89 | { 90 | // sum 91 | push(p1); 92 | rect(); // convert polar terms, if any 93 | p1 = pop(); 94 | push(p1); 95 | real(); 96 | push_integer(2); 97 | power(); 98 | push(p1); 99 | imag(); 100 | push_integer(2); 101 | power(); 102 | add(); 103 | push_rational(1, 2); 104 | power(); 105 | simplify_trig(); 106 | } 107 | else 108 | // default (all real) 109 | push(p1); 110 | restore(); 111 | } 112 | 113 | #if SELFTEST 114 | 115 | static char *s[] = { 116 | 117 | "mag(a+i*b)", 118 | "(a^2+b^2)^(1/2)", 119 | 120 | "mag(exp(a+i*b))", 121 | "exp(a)", 122 | 123 | "mag(1)", 124 | "1", 125 | 126 | "mag(-1)", 127 | "1", 128 | 129 | "mag(1+exp(i*pi/3))", 130 | "3^(1/2)", 131 | 132 | "mag((a+i*b)/(c+i*d))", 133 | "(a^2+b^2)^(1/2)/((c^2+d^2)^(1/2))", 134 | 135 | "mag(exp(i theta))", 136 | "1", 137 | 138 | "mag(exp(-i theta))", 139 | "1", 140 | 141 | "mag((-1)^theta)", 142 | "1", 143 | 144 | "mag((-1)^(-theta))", 145 | "1", 146 | 147 | "mag(3*(-1)^theta)", 148 | "3", 149 | 150 | "mag(3*(-1)^(-theta))", 151 | "3", 152 | 153 | "mag(-3*(-1)^theta)", 154 | "3", 155 | 156 | "mag(-3*(-1)^(-theta))", 157 | "3", 158 | }; 159 | 160 | void 161 | test_mag(void) 162 | { 163 | test(__FILE__, s, sizeof s / sizeof (char *)); 164 | } 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mcmp.cpp: -------------------------------------------------------------------------------- 1 | // Bignum compare 2 | // 3 | // returns 4 | // 5 | // -1 a < b 6 | // 7 | // 0 a = b 8 | // 9 | // 1 a > b 10 | 11 | #include "../Headers/defs.h" 12 | 13 | int 14 | mcmp(unsigned int *a, unsigned int *b) 15 | { 16 | int i; 17 | 18 | if (MSIGN(a) == -1 && MSIGN(b) == 1) 19 | return -1; 20 | 21 | if (MSIGN(a) == 1 && MSIGN(b) == -1) 22 | return 1; 23 | 24 | // same sign 25 | 26 | if (MLENGTH(a) < MLENGTH(b)) 27 | { 28 | if (MSIGN(a) == 1) 29 | return -1; 30 | else 31 | return 1; 32 | } 33 | 34 | if (MLENGTH(a) > MLENGTH(b)) 35 | { 36 | if (MSIGN(a) == 1) 37 | return 1; 38 | else 39 | return -1; 40 | } 41 | 42 | // same length 43 | 44 | for (i = MLENGTH(a) - 1; i > 0; i--) 45 | if (a[i] != b[i]) 46 | break; 47 | 48 | if (a[i] < b[i]) 49 | { 50 | if (MSIGN(a) == 1) 51 | return -1; 52 | else 53 | return 1; 54 | } 55 | 56 | if (a[i] > b[i]) 57 | { 58 | if (MSIGN(a) == 1) 59 | return 1; 60 | else 61 | return -1; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | int 68 | mcmpint(unsigned int *a, int n) 69 | { 70 | int t; 71 | unsigned int *b; 72 | b = mint(n); 73 | t = mcmp(a, b); 74 | mfree(b); 75 | return t; 76 | } 77 | 78 | #if SELFTEST 79 | 80 | void 81 | test_mcmp(void) 82 | { 83 | int i, j, k; 84 | unsigned int *x, *y; 85 | logout("testing mcmp\n"); 86 | for (i = -1000; i < 1000; i++) { 87 | x = mint(i); 88 | for (j = -1000; j < 1000; j++) { 89 | y = mint(j); 90 | k = mcmp(x, y); 91 | if (i == j && k != 0) { 92 | logout("failed\n"); 93 | errout(); 94 | } 95 | if (i < j && k != -1) { 96 | logout("failed\n"); 97 | errout(); 98 | } 99 | if (i > j && k != 1) { 100 | logout("failed\n"); 101 | errout(); 102 | } 103 | mfree(y); 104 | } 105 | mfree(x); 106 | } 107 | logout("ok\n"); 108 | } 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mfactor.cpp: -------------------------------------------------------------------------------- 1 | // For odd n, returns the largest factor less than or equal to sqrt(n) 2 | 3 | #if 0 // not used anymore 4 | 5 | unsigned int * 6 | mfactor(unsigned int *n) 7 | { 8 | unsigned int *r, *root, *t, *two, *x, *y; 9 | 10 | two = mint(2); 11 | 12 | root = msqrt(n); 13 | 14 | // y = 1; 15 | 16 | y = mint(1); 17 | 18 | // x = 2 isqrt(n) + 1 19 | 20 | t = madd(root, root); 21 | x = madd(t, y); 22 | mfree(t); 23 | 24 | // r = isqrt(n) ^ 2 - n 25 | 26 | t = mmul(root, root); 27 | r = msub(t, n); 28 | mfree(t); 29 | 30 | mfree(root); 31 | 32 | while (1) { 33 | 34 | if (MZERO(r)) { 35 | 36 | // n = (x - y) / 2 37 | 38 | t = msub(x, y); 39 | n = mdiv(t, two); 40 | mfree(t); 41 | 42 | mfree(r); 43 | mfree(x); 44 | mfree(y); 45 | mfree(two); 46 | 47 | return n; 48 | } 49 | 50 | // r = r + x 51 | 52 | t = madd(r, x); 53 | mfree(r); 54 | r = t; 55 | 56 | // x = x + 2 57 | 58 | t = madd(x, two); 59 | mfree(x); 60 | x = t; 61 | 62 | while (1) { 63 | 64 | // r = r - y 65 | 66 | t = msub(r, y); 67 | mfree(r); 68 | r = t; 69 | 70 | // y = y + 2 71 | 72 | t = madd(y, two); 73 | mfree(y); 74 | y = t; 75 | 76 | if (MSIGN(r) == -1 || MZERO(r)) 77 | break; 78 | } 79 | } 80 | } 81 | 82 | void 83 | test_mfactor(void) 84 | { 85 | unsigned int *n; 86 | n = mint(377); 87 | n = mfactor(n); 88 | printf("%d\n", n[0]); 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mgcd.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Bignum GCD 4 | // 5 | // Uses the binary GCD algorithm. 6 | // 7 | // See "The Art of Computer Programming" p. 338. 8 | // 9 | // mgcd always returns a positive value 10 | // 11 | // mgcd(0, 0) = 0 12 | // 13 | // mgcd(u, 0) = |u| 14 | // 15 | // mgcd(0, v) = |v| 16 | // 17 | //----------------------------------------------------------------------------- 18 | 19 | #include "../Headers/defs.h" 20 | 21 | unsigned int * 22 | mgcd(unsigned int *u, unsigned int *v) 23 | { 24 | int i, k, n; 25 | unsigned int *t; 26 | 27 | if (MZERO(u)) 28 | { 29 | t = mcopy(v); 30 | MSIGN(t) = 1; 31 | return t; 32 | } 33 | 34 | if (MZERO(v)) 35 | { 36 | t = mcopy(u); 37 | MSIGN(t) = 1; 38 | return t; 39 | } 40 | 41 | u = mcopy(u); 42 | v = mcopy(v); 43 | 44 | MSIGN(u) = 1; 45 | MSIGN(v) = 1; 46 | 47 | k = 0; 48 | 49 | while ((u[0] & 1) == 0 && (v[0] & 1) == 0) 50 | { 51 | mshiftright(u); 52 | mshiftright(v); 53 | k++; 54 | } 55 | 56 | if (u[0] & 1) 57 | { 58 | t = mcopy(v); 59 | MSIGN(t) *= -1; 60 | } 61 | else 62 | t = mcopy(u); 63 | 64 | while (1) 65 | { 66 | 67 | while ((t[0] & 1) == 0) 68 | mshiftright(t); 69 | 70 | if (MSIGN(t) == 1) 71 | { 72 | mfree(u); 73 | u = mcopy(t); 74 | } 75 | else 76 | { 77 | mfree(v); 78 | v = mcopy(t); 79 | MSIGN(v) *= -1; 80 | } 81 | 82 | mfree(t); 83 | 84 | t = msub(u, v); 85 | 86 | if (MZERO(t)) 87 | { 88 | mfree(t); 89 | mfree(v); 90 | n = (k / 32) + 1; 91 | v = mnew(n); 92 | MSIGN(v) = 1; 93 | MLENGTH(v) = n; 94 | for (i = 0; i < n; i++) 95 | v[i] = 0; 96 | mp_set_bit(v, k); 97 | t = mmul(u, v); 98 | mfree(u); 99 | mfree(v); 100 | return t; 101 | } 102 | } 103 | } 104 | 105 | #if SELFTEST 106 | 107 | static unsigned int *egcd(unsigned int *, unsigned int *); 108 | 109 | void 110 | test_mgcd(void) 111 | { 112 | int i, j, n; 113 | unsigned int *a, *b, *c, *d; 114 | logout("testing mgcd\n"); 115 | n = mtotal; 116 | for (i = 1; i < 100; i++) { 117 | a = mint(i); 118 | for (j = 1; j < 100; j++) { 119 | b = mint(j); 120 | c = mgcd(a, b); 121 | d = egcd(a, b); 122 | if (mcmp(c, d) != 0) { 123 | logout("failed\n"); 124 | errout(); 125 | } 126 | mfree(b); 127 | mfree(c); 128 | mfree(d); 129 | } 130 | mfree(a); 131 | } 132 | if (n != mtotal) { 133 | logout("memory leak\n"); 134 | errout(); 135 | } 136 | logout("ok\n"); 137 | } 138 | 139 | // Euclid's algorithm 140 | 141 | static unsigned int * 142 | egcd(unsigned int *a, unsigned int *b) 143 | { 144 | int sign; 145 | unsigned int *c; 146 | if (MZERO(b)) 147 | stop("divide by zero"); 148 | b = mcopy(b); 149 | if (MZERO(a)) 150 | return b; 151 | sign = MSIGN(b); 152 | a = mcopy(a); 153 | while (!MZERO(b)) { 154 | c = mmod(a, b); 155 | mfree(a); 156 | a = b; 157 | b = c; 158 | } 159 | mfree(b); 160 | MSIGN(a) = sign; 161 | return a; 162 | } 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mmodpow.cpp: -------------------------------------------------------------------------------- 1 | // Bignum modular power (x^n mod m) 2 | 3 | #include "../Headers/defs.h" 4 | 5 | // could do indexed bit test instead of shift right 6 | 7 | unsigned int * 8 | mmodpow(unsigned int *x, unsigned int *n, unsigned int *m) 9 | { 10 | unsigned int *y, *z; 11 | x = mcopy(x); 12 | n = mcopy(n); 13 | y = mint(1); 14 | while (1) 15 | { 16 | if (n[0] & 1) 17 | { 18 | z = mmul(y, x); 19 | mfree(y); 20 | y = mmod(z, m); 21 | mfree(z); 22 | } 23 | mshiftright(n); 24 | if (MZERO(n)) 25 | break; 26 | z = mmul(x, x); 27 | mfree(x); 28 | x = mmod(z, m); 29 | mfree(z); 30 | } 31 | mfree(x); 32 | mfree(n); 33 | return y; 34 | } 35 | 36 | #if SELFTEST 37 | 38 | void 39 | test_mmodpow(void) 40 | { 41 | int mem; 42 | int x, n, m; 43 | unsigned int *xx, *nn, *mm, *y; 44 | mem = mtotal; 45 | for (x = 1; x < 100; x++) { 46 | xx = mint(x); 47 | for (n = 1; n < 100; n++) { 48 | nn = mint(n); 49 | for (m = 1; m < 10; m++) { 50 | mm = mint(m); 51 | y = mmodpow(xx, nn, mm); 52 | mfree(y); 53 | mfree(mm); 54 | } 55 | mfree(nn); 56 | } 57 | mfree(xx); 58 | } 59 | if (mem != mtotal) { 60 | /* 61 | sprintf(logbuf, "mmodpow memory leak %d %d\n", mem, mtotal); 62 | logout(logbuf); 63 | */ 64 | errout(); 65 | } 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mod.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void mod(void); 6 | 7 | void 8 | eval_mod(void) 9 | { 10 | push(cadr(p1)); 11 | eval(); 12 | push(caddr(p1)); 13 | eval(); 14 | mod(); 15 | } 16 | 17 | void 18 | mod(void) 19 | { 20 | int n; 21 | 22 | save(); 23 | 24 | p2 = pop(); 25 | p1 = pop(); 26 | 27 | if (iszero(p2)) 28 | stop("mod function: divide by zero"); 29 | 30 | if (!isnum(p1) || !isnum(p2)) 31 | { 32 | push_symbol(MOD); 33 | push(p1); 34 | push(p2); 35 | list(3); 36 | restore(); 37 | return; 38 | } 39 | 40 | if (isdouble(p1)) 41 | { 42 | push(p1); 43 | n = pop_integer(); 44 | if (n == (int)0x80000000) 45 | stop("mod function: cannot convert float value to integer"); 46 | push_integer(n); 47 | p1 = pop(); 48 | } 49 | 50 | if (isdouble(p2)) 51 | { 52 | push(p2); 53 | n = pop_integer(); 54 | if (n == (int)0x80000000) 55 | stop("mod function: cannot convert float value to integer"); 56 | push_integer(n); 57 | p2 = pop(); 58 | } 59 | 60 | if (!isinteger(p1) || !isinteger(p2)) 61 | stop("mod function: integer arguments expected"); 62 | 63 | p3 = alloc(); 64 | p3->k = NUM; 65 | p3->u.q.a = mmod(p1->u.q.a, p2->u.q.a); 66 | p3->u.q.b = mint(1); 67 | push(p3); 68 | 69 | restore(); 70 | } 71 | 72 | #if SELFTEST 73 | 74 | static char *s[] = { 75 | 76 | "mod(2.0,3.0)", 77 | "2", 78 | 79 | "mod(-2.0,3.0)", 80 | "-2", 81 | 82 | "mod(2.0,-3.0)", 83 | "2", 84 | 85 | "mod(-2.0,-3.0)", 86 | "-2", 87 | 88 | "mod(2,3)", 89 | "2", 90 | 91 | "mod(-2,3)", 92 | "-2", 93 | 94 | "mod(2,-3)", 95 | "2", 96 | 97 | "mod(-2,-3)", 98 | "-2", 99 | 100 | "mod(a,b)", 101 | "mod(a,b)", 102 | 103 | "mod(2.0,0.0)", 104 | "Stop: mod function: divide by zero", 105 | 106 | "mod(2,0)", 107 | "Stop: mod function: divide by zero", 108 | 109 | "mod(1.2,2)", 110 | "Stop: mod function: cannot convert float value to integer", 111 | 112 | "mod(1/2,3)", 113 | "Stop: mod function: integer arguments expected", 114 | 115 | "mod(15,8.0)", 116 | "7", 117 | }; 118 | 119 | void 120 | test_mod(void) 121 | { 122 | test(__FILE__, s, sizeof s / sizeof (char *)); 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mpow.cpp: -------------------------------------------------------------------------------- 1 | // Bignum power 2 | 3 | #include "../Headers/defs.h" 4 | 5 | unsigned int * 6 | mpow(unsigned int *a, unsigned int n) 7 | { 8 | unsigned int *aa, *t; 9 | 10 | a = mcopy(a); 11 | 12 | aa = mint(1); 13 | 14 | for (;;) 15 | { 16 | 17 | if (n & 1) 18 | { 19 | t = mmul(aa, a); 20 | mfree(aa); 21 | aa = t; 22 | } 23 | 24 | n >>= 1; 25 | 26 | if (n == 0) 27 | break; 28 | 29 | t = mmul(a, a); 30 | mfree(a); 31 | a = t; 32 | } 33 | 34 | mfree(a); 35 | 36 | return aa; 37 | } 38 | 39 | #if SELFTEST 40 | 41 | void 42 | test_mpow(void) 43 | { 44 | int i, j, mem, x; 45 | unsigned int *a, *b, *c; 46 | 47 | logout("testing mpow\n"); 48 | 49 | mem = mtotal; 50 | 51 | // small numbers 52 | 53 | for (i = -10; i < 10; i++) { 54 | a = mint(i); 55 | x = 1; 56 | for (j = 0; j < 10; j++) { 57 | b = mpow(a, j); 58 | c = mint(x); 59 | if (mcmp(b, c) != 0) { 60 | /* 61 | sprintf(logbuf, "failed a=%d b=%d c=%d\n", a[0], b[0], c[0]); 62 | logout(logbuf); 63 | */ 64 | errout(); 65 | } 66 | mfree(b); 67 | mfree(c); 68 | x *= i; 69 | } 70 | mfree(a); 71 | } 72 | 73 | if (mem != mtotal) { 74 | logout("memory leak\n"); 75 | errout(); 76 | } 77 | 78 | logout("ok\n"); 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mprime.cpp: -------------------------------------------------------------------------------- 1 | // Bignum prime test (returns 1 if prime, 0 if not) 2 | 3 | // Uses Algorithm P (probabilistic primality test) from p. 395 of 4 | // "The Art of Computer Programming, Volume 2" by Donald E. Knuth. 5 | 6 | #include "../Headers/defs.h" 7 | 8 | static int mprimef(unsigned int *, unsigned int *, int); 9 | 10 | int 11 | mprime(unsigned int *n) 12 | { 13 | int i, k; 14 | unsigned int *q; 15 | 16 | // 1? 17 | 18 | if (MLENGTH(n) == 1 && n[0] == 1) 19 | return 0; 20 | 21 | // 2? 22 | 23 | if (MLENGTH(n) == 1 && n[0] == 2) 24 | return 1; 25 | 26 | // even? 27 | 28 | if ((n[0] & 1) == 0) 29 | return 0; 30 | 31 | // n = 1 + (2 ^ k) q 32 | 33 | q = mcopy(n); 34 | 35 | k = 0; 36 | do 37 | { 38 | mshiftright(q); 39 | k++; 40 | } 41 | while ((q[0] & 1) == 0); 42 | 43 | // try 25 times 44 | 45 | for (i = 0; i < 25; i++) 46 | if (mprimef(n, q, k) == 0) 47 | break; 48 | 49 | mfree(q); 50 | 51 | if (i < 25) 52 | return 0; 53 | else 54 | return 1; 55 | } 56 | 57 | //----------------------------------------------------------------------------- 58 | // 59 | // This is the actual implementation of Algorithm P. 60 | // 61 | // Input: n The number in question. 62 | // 63 | // q n = 1 + (2 ^ k) q 64 | // 65 | // k 66 | // 67 | // Output: 1 when n is probably prime 68 | // 69 | // 0 when n is definitely not prime 70 | // 71 | //----------------------------------------------------------------------------- 72 | 73 | static int 74 | mprimef(unsigned int *n, unsigned int *q, int k) 75 | { 76 | int i, j; 77 | unsigned int *t, *x, *y; 78 | 79 | // generate x 80 | 81 | t = mcopy(n); 82 | 83 | while (1) 84 | { 85 | for (i = 0; i < MLENGTH(t); i++) 86 | t[i] = rand(); 87 | x = mmod(t, n); 88 | if (!MZERO(x) && !MEQUAL(x, 1)) 89 | break; 90 | mfree(x); 91 | } 92 | 93 | mfree(t); 94 | 95 | // exponentiate 96 | 97 | y = mmodpow(x, q, n); 98 | 99 | // done? 100 | 101 | if (MEQUAL(y, 1)) 102 | { 103 | mfree(x); 104 | mfree(y); 105 | return 1; 106 | } 107 | 108 | j = 0; 109 | 110 | while (1) 111 | { 112 | 113 | // y = n - 1? 114 | 115 | t = msub(n, y); 116 | 117 | if (MEQUAL(t, 1)) 118 | { 119 | mfree(t); 120 | mfree(x); 121 | mfree(y); 122 | return 1; 123 | } 124 | 125 | mfree(t); 126 | 127 | if (++j == k) 128 | { 129 | mfree(x); 130 | mfree(y); 131 | return 0; 132 | } 133 | 134 | // y = (y ^ 2) mod n 135 | 136 | t = mmul(y, y); 137 | mfree(y); 138 | y = mmod(t, n); 139 | mfree(t); 140 | 141 | // y = 1? 142 | 143 | if (MEQUAL(y, 1)) 144 | { 145 | mfree(x); 146 | mfree(y); 147 | return 0; 148 | } 149 | } 150 | } 151 | 152 | #if SELFTEST 153 | 154 | void 155 | test_mprime(void) 156 | { 157 | int i, k, m, t; 158 | unsigned int *n; 159 | logout("test mprime\n"); 160 | m = mtotal; 161 | k = 0; 162 | for (i = 0; i < 10000; i++) { 163 | n = mint(i); 164 | t = mprime(n); 165 | mfree(n); 166 | if (i == primetab[k]) { 167 | if (t == 0) { 168 | /* 169 | sprintf(logbuf, "failed for prime number %d\n", i); 170 | logout(logbuf); 171 | */ 172 | errout(); 173 | } 174 | k++; 175 | } else if (t == 1) { 176 | /* 177 | sprintf(logbuf, "failed for composite number %d\n", i); 178 | logout(logbuf); 179 | */ 180 | errout(); 181 | } 182 | } 183 | if (m != mtotal) { 184 | logout("memory leak\n"); 185 | errout(); 186 | } 187 | logout("ok\n"); 188 | } 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mroot.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Bignum root 4 | // 5 | // Returns null pointer if not perfect root. 6 | // 7 | // The sign of the radicand is ignored. 8 | // 9 | //----------------------------------------------------------------------------- 10 | 11 | #include "../Headers/defs.h" 12 | 13 | unsigned int * 14 | mroot(unsigned int *n, unsigned int index) 15 | { 16 | int i, j, k; 17 | unsigned int m, *x, *y; 18 | 19 | if (index == 0) 20 | stop("root index is zero"); 21 | 22 | // count number of bits 23 | 24 | k = 32 * (MLENGTH(n) - 1); 25 | 26 | m = n[MLENGTH(n) - 1]; 27 | 28 | while (m) 29 | { 30 | m >>= 1; 31 | k++; 32 | } 33 | 34 | if (k == 0) 35 | return mint(0); 36 | 37 | // initial guess 38 | 39 | k = (k - 1) / index; 40 | 41 | j = k / 32 + 1; 42 | x = mnew(j); 43 | MSIGN(x) = 1; 44 | MLENGTH(x) = j; 45 | for (i = 0; i < j; i++) 46 | x[i] = 0; 47 | 48 | while (k >= 0) 49 | { 50 | mp_set_bit(x, k); 51 | y = mpow(x, index); 52 | switch (mcmp(y, n)) 53 | { 54 | case -1: 55 | break; 56 | case 0: 57 | mfree(y); 58 | return x; 59 | case 1: 60 | mp_clr_bit(x, k); 61 | break; 62 | } 63 | mfree(y); 64 | k--; 65 | } 66 | 67 | mfree(x); 68 | 69 | return 0; 70 | } 71 | 72 | #if SELFTEST 73 | 74 | void 75 | test_mroot(void) 76 | { 77 | int i, j, mem; 78 | unsigned int *a, *b, *c; 79 | 80 | logout("testing mroot\n"); 81 | 82 | mem = mtotal; 83 | 84 | // small numbers 85 | 86 | for (i = 0; i < 10; i++) { 87 | a = mint(i); 88 | for (j = 1; j < 10; j++) { 89 | b = mpow(a, j); 90 | c = mroot(b, j); 91 | if (c == 0 || mcmp(a, c) != 0) { 92 | /* 93 | sprintf(logbuf, "failed a=%d b=%d c=%d\n", a[0], b[0], c[0]); 94 | logout(logbuf); 95 | */ 96 | errout(); 97 | } 98 | mfree(b); 99 | mfree(c); 100 | } 101 | mfree(a); 102 | } 103 | 104 | a = mint(12345); 105 | 106 | for (i = 1; i < 10; i++) { 107 | b = mpow(a, i); 108 | c = mroot(b, i); 109 | if (c == 0 || mcmp(a, c) != 0) { 110 | logout("failed\n"); 111 | errout(); 112 | } 113 | mfree(b); 114 | mfree(c); 115 | } 116 | 117 | mfree(a); 118 | 119 | if (mtotal != mem) { 120 | logout("memory leak\n"); 121 | errout(); 122 | } 123 | 124 | logout("ok\n"); 125 | } 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mscan.cpp: -------------------------------------------------------------------------------- 1 | // bignum scanner 2 | 3 | #include "../Headers/defs.h" 4 | 5 | static unsigned int *addf(unsigned int *, int); 6 | static unsigned int *mulf(unsigned int *, int); 7 | 8 | unsigned int * 9 | mscan(char *s) 10 | { 11 | int sign; 12 | unsigned int *a, *b, *c; 13 | 14 | sign = 1; 15 | 16 | if (*s == '-') 17 | { 18 | sign = -1; 19 | s++; 20 | } 21 | 22 | a = mint(0); 23 | 24 | while (*s) 25 | { 26 | b = mulf(a, 10); 27 | c = addf(b, *s - '0'); 28 | mfree(a); 29 | mfree(b); 30 | a = c; 31 | s++; 32 | } 33 | 34 | if (!MZERO(a)) 35 | MSIGN(a) *= sign; 36 | 37 | return a; 38 | } 39 | 40 | static unsigned int * 41 | addf(unsigned int *a, int n) 42 | { 43 | unsigned int *b, *c; 44 | b = mint(n); 45 | c = madd(a, b); 46 | mfree(b); 47 | return c; 48 | } 49 | 50 | static unsigned int * 51 | mulf(unsigned int *a, int n) 52 | { 53 | unsigned int *b, *c; 54 | b = mint(n); 55 | c = mmul(a, b); 56 | mfree(b); 57 | return c; 58 | } 59 | -------------------------------------------------------------------------------- /Eigenmath/Sources/msqrt.cpp: -------------------------------------------------------------------------------- 1 | // Bignum square root 2 | 3 | #if 0 // not used anymore 4 | 5 | unsigned int * 6 | msqrt(unsigned int *n) 7 | { 8 | int i, k, kk; 9 | unsigned int m, *x, *y; 10 | 11 | if (MLENGTH(n) == 1 && n[0] == 0) { 12 | x = mint(0); 13 | return x; 14 | } 15 | 16 | // count number of bits 17 | 18 | k = 32 * (MLENGTH(n) - 1); 19 | 20 | m = n[MLENGTH(n) - 1]; 21 | 22 | while (m) { 23 | m >>= 1; 24 | k++; 25 | } 26 | 27 | k = (k - 1) / 2; 28 | 29 | // initial guess 30 | 31 | kk = k / 32 + 1; 32 | x = mnew(kk); 33 | MSIGN(x) = 1; 34 | MLENGTH(x) = kk; 35 | for (i = 0; i < kk; i++) 36 | x[i] = 0; 37 | mp_set_bit(x, k); 38 | 39 | while (--k >= 0) { 40 | mp_set_bit(x, k); 41 | y = mmul(x, x); 42 | if (mcmp(y, n) == 1) 43 | mp_clr_bit(x, k); 44 | mfree(y); 45 | } 46 | 47 | return x; 48 | } 49 | 50 | void 51 | test_msqrt(void) 52 | { 53 | int i; 54 | unsigned int *n, *x, *y; 55 | logout("testing msqrt\n"); 56 | for (i = 0; i < 1000000; i++) { 57 | n = mint(i); 58 | x = msqrt(n); 59 | y = mint((int) (sqrt((double) i) + 1e-10)); 60 | if (mcmp(x, y) != 0) { 61 | /* 62 | sprintf(logbuf, "failed for %d got %u\n", i, x[0]); 63 | logout(logbuf); 64 | */ 65 | errout(); 66 | } 67 | mfree(n); 68 | mfree(x); 69 | mfree(y); 70 | } 71 | logout("ok\n"); 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /Eigenmath/Sources/mstr.cpp: -------------------------------------------------------------------------------- 1 | // Convert bignum to string 2 | 3 | #include "../Headers/defs.h" 4 | 5 | static int divby1billion(unsigned int *); 6 | 7 | static char *str; 8 | static int len; 9 | 10 | char * 11 | mstr(unsigned int *a) 12 | { 13 | int k, n, r, sign; 14 | char c; 15 | 16 | if (str == NULL) 17 | { 18 | str = (char *)malloc(1000); 19 | len = 1000; 20 | } 21 | 22 | // estimate string size 23 | 24 | n = 10 * MLENGTH(a) + 2; 25 | 26 | if (n > len) 27 | { 28 | free(str); 29 | str = (char *)malloc(n); 30 | len = n; 31 | } 32 | 33 | sign = MSIGN(a); 34 | 35 | a = mcopy(a); 36 | 37 | k = len - 1; 38 | 39 | str[k] = 0; 40 | 41 | for (;;) 42 | { 43 | k -= 9; 44 | r = divby1billion(a); 45 | c = str[k + 9]; 46 | sprintf(str + k, "%09d", r); 47 | str[k + 9] = c; 48 | if (MZERO(a)) 49 | break; 50 | } 51 | 52 | // remove leading zeroes 53 | 54 | while (str[k] == '0') 55 | k++; 56 | 57 | if (str[k] == 0) 58 | k--; 59 | 60 | // sign 61 | 62 | if (sign == -1) 63 | { 64 | k--; 65 | str[k] = '-'; 66 | } 67 | 68 | mfree(a); 69 | 70 | return str + k; 71 | } 72 | 73 | // Returns remainder as function value, quotient returned in a. 74 | 75 | static int 76 | divby1billion(unsigned int *a) 77 | { 78 | int i; 79 | unsigned long long kk; 80 | 81 | kk = 0; 82 | 83 | for (i = MLENGTH(a) - 1; i >= 0; i--) 84 | { 85 | 86 | if (little_endian()) 87 | { 88 | ((unsigned int *)&kk)[1] = ((unsigned int *)&kk)[0]; 89 | ((unsigned int *)&kk)[0] = a[i]; 90 | } 91 | else 92 | { 93 | ((unsigned int *)&kk)[0] = ((unsigned int *)&kk)[1]; 94 | ((unsigned int *)&kk)[1] = a[i]; 95 | } 96 | 97 | a[i] = (int)(kk / 1000000000); 98 | 99 | kk -= (unsigned long long)1000000000 * a[i]; 100 | } 101 | 102 | // length of quotient 103 | 104 | for (i = MLENGTH(a) - 1; i > 0; i--) 105 | if (a[i]) 106 | break; 107 | 108 | MLENGTH(a) = i + 1; 109 | 110 | if (little_endian()) 111 | return ((unsigned int *)&kk)[0]; 112 | else 113 | return ((unsigned int *)&kk)[1]; 114 | } 115 | -------------------------------------------------------------------------------- /Eigenmath/Sources/numerator.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_numerator(void) 6 | { 7 | push(cadr(p1)); 8 | eval(); 9 | numerator(); 10 | } 11 | 12 | void 13 | numerator(void) 14 | { 15 | int h; 16 | 17 | save(); 18 | 19 | p1 = pop(); 20 | 21 | if (car(p1) == symbol(ADD)) 22 | { 23 | push(p1); 24 | rationalize(); 25 | p1 = pop(); 26 | } 27 | 28 | if (car(p1) == symbol(MULTIPLY)) 29 | { 30 | h = tos; 31 | p1 = cdr(p1); 32 | while (iscons(p1)) 33 | { 34 | push(car(p1)); 35 | numerator(); 36 | p1 = cdr(p1); 37 | } 38 | multiply_all(tos - h); 39 | } 40 | else if (isrational(p1)) 41 | { 42 | push(p1); 43 | mp_numerator(); 44 | } 45 | else if (car(p1) == symbol(POWER) && isnegativeterm(caddr(p1))) 46 | push(one); 47 | else 48 | push(p1); 49 | 50 | restore(); 51 | } 52 | 53 | #if SELFTEST 54 | 55 | static char *s[] = { 56 | 57 | "numerator(2/3)", 58 | "2", 59 | 60 | "numerator(x)", 61 | "x", 62 | 63 | "numerator(1/x)", 64 | "1", 65 | 66 | "numerator(a+b)", 67 | "a+b", 68 | 69 | "numerator(1/a+1/b)", 70 | "a+b", 71 | }; 72 | 73 | void 74 | test_numerator(void) 75 | { 76 | test(__FILE__, s, sizeof s / sizeof (char *)); 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /Eigenmath/Sources/outer.cpp: -------------------------------------------------------------------------------- 1 | // Outer product of tensors 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_outer(void) 7 | { 8 | p1 = cdr(p1); 9 | push(car(p1)); 10 | eval(); 11 | p1 = cdr(p1); 12 | while (iscons(p1)) 13 | { 14 | push(car(p1)); 15 | eval(); 16 | outer(); 17 | p1 = cdr(p1); 18 | } 19 | } 20 | 21 | void 22 | outer(void) 23 | { 24 | save(); 25 | p2 = pop(); 26 | p1 = pop(); 27 | if (istensor(p1) && istensor(p2)) 28 | yyouter(); 29 | else 30 | { 31 | push(p1); 32 | push(p2); 33 | if (istensor(p1)) 34 | tensor_times_scalar(); 35 | else if (istensor(p2)) 36 | scalar_times_tensor(); 37 | else 38 | multiply(); 39 | } 40 | restore(); 41 | } 42 | 43 | void 44 | yyouter(void) 45 | { 46 | int i, j, k, ndim, nelem; 47 | 48 | ndim = p1->u.tensor->ndim + p2->u.tensor->ndim; 49 | 50 | if (ndim > MAXDIM) 51 | stop("outer: rank of result exceeds maximum"); 52 | 53 | nelem = p1->u.tensor->nelem * p2->u.tensor->nelem; 54 | 55 | p3 = alloc_tensor(nelem); 56 | 57 | p3->u.tensor->ndim = ndim; 58 | 59 | for (i = 0; i < p1->u.tensor->ndim; i++) 60 | p3->u.tensor->dim[i] = p1->u.tensor->dim[i]; 61 | 62 | j = i; 63 | 64 | for (i = 0; i < p2->u.tensor->ndim; i++) 65 | p3->u.tensor->dim[j + i] = p2->u.tensor->dim[i]; 66 | 67 | k = 0; 68 | 69 | for (i = 0; i < p1->u.tensor->nelem; i++) 70 | for (j = 0; j < p2->u.tensor->nelem; j++) 71 | { 72 | push(p1->u.tensor->elem[i]); 73 | push(p2->u.tensor->elem[j]); 74 | multiply(); 75 | p3->u.tensor->elem[k++] = pop(); 76 | } 77 | 78 | push(p3); 79 | } 80 | 81 | #if SELFTEST 82 | 83 | static char *s[] = { 84 | 85 | "outer(a,b)", 86 | "a*b", 87 | 88 | "outer(a,(b1,b2))", 89 | "(a*b1,a*b2)", 90 | 91 | "outer((a1,a2),b)", 92 | "(a1*b,a2*b)", 93 | 94 | "H33=hilbert(3)", 95 | "", 96 | 97 | "H44=hilbert(4)", 98 | "", 99 | 100 | "H55=hilbert(5)", 101 | "", 102 | 103 | "H3344=outer(H33,H44)", 104 | "", 105 | 106 | "H4455=outer(H44,H55)", 107 | "", 108 | 109 | "H33444455=outer(H33,H44,H44,H55)", 110 | "", 111 | 112 | "simplify(inner(H3344,H4455)-contract(H33444455,4,5))", 113 | "0", 114 | }; 115 | 116 | void 117 | test_outer(void) 118 | { 119 | test(__FILE__, s, sizeof s / sizeof (char *)); 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /Eigenmath/Sources/partition.cpp: -------------------------------------------------------------------------------- 1 | /* Partition a term 2 | 3 | Input stack: 4 | 5 | term (factor or product of factors) 6 | 7 | free variable 8 | 9 | Output stack: 10 | 11 | constant expression 12 | 13 | variable expression 14 | */ 15 | 16 | #include "../Headers/defs.h" 17 | 18 | void 19 | partition(void) 20 | { 21 | save(); 22 | 23 | p2 = pop(); 24 | p1 = pop(); 25 | 26 | push_integer(1); 27 | 28 | p3 = pop(); 29 | p4 = p3; 30 | 31 | p1 = cdr(p1); 32 | 33 | while (iscons(p1)) 34 | { 35 | if (find(car(p1), p2)) 36 | { 37 | push(p4); 38 | push(car(p1)); 39 | multiply(); 40 | p4 = pop(); 41 | } 42 | else 43 | { 44 | push(p3); 45 | push(car(p1)); 46 | multiply(); 47 | p3 = pop(); 48 | } 49 | p1 = cdr(p1); 50 | } 51 | 52 | push(p3); 53 | push(p4); 54 | 55 | restore(); 56 | } 57 | -------------------------------------------------------------------------------- /Eigenmath/Sources/polar.cpp: -------------------------------------------------------------------------------- 1 | /* Convert complex z to polar form 2 | 3 | Input: push z 4 | 5 | Output: Result on stack 6 | 7 | polar(z) = mag(z) * exp(i * arg(z)) 8 | */ 9 | 10 | #include "../Headers/defs.h" 11 | 12 | void 13 | eval_polar(void) 14 | { 15 | push(cadr(p1)); 16 | eval(); 17 | polar(); 18 | } 19 | 20 | void 21 | polar(void) 22 | { 23 | save(); 24 | p1 = pop(); 25 | push(p1); 26 | mag(); 27 | push(imaginaryunit); 28 | push(p1); 29 | arg(); 30 | multiply(); 31 | exponential(); 32 | multiply(); 33 | restore(); 34 | } 35 | 36 | #if SELFTEST 37 | 38 | static char *s[] = { 39 | 40 | "polar(1+i)", 41 | "2^(1/2)*exp(1/4*i*pi)", 42 | 43 | "polar(-1+i)", 44 | "2^(1/2)*exp(3/4*i*pi)", 45 | 46 | "polar(-1-i)", 47 | "2^(1/2)*exp(-3/4*i*pi)", 48 | 49 | "polar(1-i)", 50 | "2^(1/2)*exp(-1/4*i*pi)", 51 | 52 | "rect(polar(3+4*i))", 53 | "3+4*i", 54 | 55 | "rect(polar(-3+4*i))", 56 | "-3+4*i", 57 | 58 | "rect(polar(3-4*i))", 59 | "3-4*i", 60 | 61 | "rect(polar(-3-4*i))", 62 | "-3-4*i", 63 | }; 64 | 65 | void 66 | test_polar(void) 67 | { 68 | test(__FILE__, s, sizeof s / sizeof (char *)); 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /Eigenmath/Sources/prime.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Look up the nth prime 4 | // 5 | // Input: n on stack (0 < n < 10001) 6 | // 7 | // Output: nth prime on stack 8 | // 9 | //----------------------------------------------------------------------------- 10 | 11 | #include "../Headers/defs.h" 12 | 13 | void 14 | eval_prime(void) 15 | { 16 | push(cadr(p1)); 17 | eval(); 18 | prime(); 19 | } 20 | 21 | void 22 | prime(void) 23 | { 24 | int n; 25 | n = pop_integer(); 26 | if (n < 1 || n > MAXPRIMETAB) 27 | stop("prime: Argument out of range."); 28 | n = primetab[n - 1]; 29 | push_integer(n); 30 | } 31 | -------------------------------------------------------------------------------- /Eigenmath/Sources/product.cpp: -------------------------------------------------------------------------------- 1 | // 'product' function 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define A p3 6 | #define B p4 7 | #define I p5 8 | #define X p6 9 | 10 | void 11 | eval_product(void) 12 | { 13 | int i, j, k; 14 | 15 | // 1st arg (quoted) 16 | 17 | X = cadr(p1); 18 | if (!issymbol(X)) 19 | stop("product: 1st arg?"); 20 | 21 | // 2nd arg 22 | 23 | push(caddr(p1)); 24 | eval(); 25 | j = pop_integer(); 26 | if (j == (int)0x80000000) 27 | stop("product: 2nd arg?"); 28 | 29 | // 3rd arg 30 | 31 | push(cadddr(p1)); 32 | eval(); 33 | k = pop_integer(); 34 | if (k == (int)0x80000000) 35 | stop("product: 3rd arg?"); 36 | 37 | // 4th arg 38 | 39 | p1 = caddddr(p1); 40 | 41 | B = get_binding(X); 42 | A = get_arglist(X); 43 | 44 | push_integer(1); 45 | 46 | for (i = j; i <= k; i++) 47 | { 48 | push_integer(i); 49 | I = pop(); 50 | set_binding(X, I); 51 | push(p1); 52 | eval(); 53 | multiply(); 54 | } 55 | 56 | set_binding_and_arglist(X, B, A); 57 | } 58 | -------------------------------------------------------------------------------- /Eigenmath/Sources/qadd.cpp: -------------------------------------------------------------------------------- 1 | // Add rational numbers 2 | // 3 | // Input: tos-2 addend 4 | // 5 | // tos-1 addend 6 | // 7 | // Output: sum on stack 8 | 9 | #include "../Headers/defs.h" 10 | 11 | void 12 | qadd(void) 13 | { 14 | unsigned int *a, *ab, *b, *ba, *c; 15 | 16 | save(); 17 | 18 | p2 = pop(); 19 | p1 = pop(); 20 | 21 | ab = mmul(p1->u.q.a, p2->u.q.b); 22 | ba = mmul(p1->u.q.b, p2->u.q.a); 23 | 24 | a = madd(ab, ba); 25 | 26 | mfree(ab); 27 | mfree(ba); 28 | 29 | // zero? 30 | 31 | if (MZERO(a)) 32 | { 33 | mfree(a); 34 | push(zero); 35 | restore(); 36 | return; 37 | } 38 | 39 | b = mmul(p1->u.q.b, p2->u.q.b); 40 | 41 | c = mgcd(a, b); 42 | 43 | MSIGN(c) = MSIGN(b); 44 | 45 | p1 = alloc(); 46 | 47 | p1->k = NUM; 48 | 49 | p1->u.q.a = mdiv(a, c); 50 | p1->u.q.b = mdiv(b, c); 51 | 52 | mfree(a); 53 | mfree(b); 54 | mfree(c); 55 | 56 | push(p1); 57 | 58 | restore(); 59 | } 60 | -------------------------------------------------------------------------------- /Eigenmath/Sources/qdiv.cpp: -------------------------------------------------------------------------------- 1 | // Divide rational numbers 2 | // 3 | // Input: tos-2 dividend 4 | // 5 | // tos-1 divisor 6 | // 7 | // Output: quotient on stack 8 | 9 | #include "../Headers/defs.h" 10 | 11 | void 12 | qdiv(void) 13 | { 14 | unsigned int *aa, *bb, *c; 15 | 16 | save(); 17 | 18 | p2 = pop(); 19 | p1 = pop(); 20 | 21 | // zero? 22 | 23 | if (MZERO(p2->u.q.a)) 24 | stop("divide by zero"); 25 | 26 | if (MZERO(p1->u.q.a)) 27 | { 28 | push(zero); 29 | restore(); 30 | return; 31 | } 32 | 33 | aa = mmul(p1->u.q.a, p2->u.q.b); 34 | bb = mmul(p1->u.q.b, p2->u.q.a); 35 | 36 | c = mgcd(aa, bb); 37 | 38 | MSIGN(c) = MSIGN(bb); 39 | 40 | p1 = alloc(); 41 | 42 | p1->k = NUM; 43 | 44 | p1->u.q.a = mdiv(aa, c); 45 | p1->u.q.b = mdiv(bb, c); 46 | 47 | mfree(aa); 48 | mfree(bb); 49 | 50 | push(p1); 51 | 52 | restore(); 53 | } 54 | -------------------------------------------------------------------------------- /Eigenmath/Sources/qmul.cpp: -------------------------------------------------------------------------------- 1 | // Multiply rational numbers 2 | // 3 | // Input: tos-2 multiplicand 4 | // 5 | // tos-1 multiplier 6 | // 7 | // Output: product on stack 8 | 9 | #include "../Headers/defs.h" 10 | 11 | void 12 | qmul(void) 13 | { 14 | unsigned int *aa, *bb, *c; 15 | 16 | save(); 17 | 18 | p2 = pop(); 19 | p1 = pop(); 20 | 21 | // zero? 22 | 23 | if (MZERO(p1->u.q.a) || MZERO(p2->u.q.a)) 24 | { 25 | push(zero); 26 | restore(); 27 | return; 28 | } 29 | 30 | aa = mmul(p1->u.q.a, p2->u.q.a); 31 | bb = mmul(p1->u.q.b, p2->u.q.b); 32 | 33 | c = mgcd(aa, bb); 34 | 35 | MSIGN(c) = MSIGN(bb); 36 | 37 | p1 = alloc(); 38 | 39 | p1->k = NUM; 40 | 41 | p1->u.q.a = mdiv(aa, c); 42 | p1->u.q.b = mdiv(bb, c); 43 | 44 | mfree(aa); 45 | mfree(bb); 46 | 47 | push(p1); 48 | 49 | restore(); 50 | } 51 | -------------------------------------------------------------------------------- /Eigenmath/Sources/qsub.cpp: -------------------------------------------------------------------------------- 1 | // Subtract rational numbers 2 | // 3 | // Input: tos-2 minuend 4 | // 5 | // tos-1 subtrahend 6 | // 7 | // Output: difference on stack 8 | 9 | #include "../Headers/defs.h" 10 | 11 | void 12 | qsub(void) 13 | { 14 | unsigned int *a, *ab, *b, *ba, *c; 15 | 16 | save(); 17 | 18 | p2 = pop(); 19 | p1 = pop(); 20 | 21 | ab = mmul(p1->u.q.a, p2->u.q.b); 22 | ba = mmul(p1->u.q.b, p2->u.q.a); 23 | 24 | a = msub(ab, ba); 25 | 26 | mfree(ab); 27 | mfree(ba); 28 | 29 | // zero? 30 | 31 | if (MZERO(a)) 32 | { 33 | mfree(a); 34 | push(zero); 35 | restore(); 36 | return; 37 | } 38 | 39 | b = mmul(p1->u.q.b, p2->u.q.b); 40 | 41 | c = mgcd(a, b); 42 | 43 | MSIGN(c) = MSIGN(b); 44 | 45 | p1 = alloc(); 46 | 47 | p1->k = NUM; 48 | 49 | p1->u.q.a = mdiv(a, c); 50 | p1->u.q.b = mdiv(b, c); 51 | 52 | mfree(a); 53 | mfree(b); 54 | mfree(c); 55 | 56 | push(p1); 57 | 58 | restore(); 59 | } 60 | -------------------------------------------------------------------------------- /Eigenmath/Sources/quickfactor.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Factor small numerical powers 4 | // 5 | // Input: tos-2 Base (positive integer < 2^31 - 1) 6 | // 7 | // tos-1 Exponent 8 | // 9 | // Output: Expr on stack 10 | // 11 | //----------------------------------------------------------------------------- 12 | 13 | #include "../Headers/defs.h" 14 | 15 | #define BASE p1 16 | #define EXPO p2 17 | 18 | static void quickpower(void); 19 | 20 | void 21 | quickfactor(void) 22 | { 23 | int h, i, n; 24 | U **s; 25 | 26 | save(); 27 | 28 | EXPO = pop(); 29 | BASE = pop(); 30 | 31 | h = tos; 32 | 33 | push(BASE); 34 | 35 | factor_small_number(); 36 | 37 | n = tos - h; 38 | 39 | s = stack + h; 40 | 41 | for (i = 0; i < n; i += 2) 42 | { 43 | push(s[i]); // factored base 44 | push(s[i + 1]); // factored exponent 45 | push(EXPO); 46 | multiply(); 47 | quickpower(); 48 | } 49 | 50 | // stack has n results from factor_number_raw() 51 | 52 | // on offset of that are all the expressions from quickpower() 53 | 54 | // multiply the quickpower() results 55 | 56 | multiply_all(tos - h - n); 57 | 58 | p1 = pop(); 59 | 60 | tos = h; 61 | 62 | push(p1); 63 | 64 | restore(); 65 | } 66 | 67 | // BASE is a prime number so power is simpler 68 | 69 | static void 70 | quickpower(void) 71 | { 72 | int expo; 73 | 74 | save(); 75 | 76 | EXPO = pop(); 77 | BASE = pop(); 78 | 79 | push(EXPO); 80 | bignum_truncate(); 81 | p3 = pop(); 82 | 83 | push(EXPO); 84 | push(p3); 85 | subtract(); 86 | p4 = pop(); 87 | 88 | // fractional part of EXPO 89 | 90 | if (!iszero(p4)) 91 | { 92 | push_symbol(POWER); 93 | push(BASE); 94 | push(p4); 95 | list(3); 96 | } 97 | 98 | push(p3); 99 | expo = pop_integer(); 100 | 101 | if (expo == (int)0x80000000) 102 | { 103 | push_symbol(POWER); 104 | push(BASE); 105 | push(p3); 106 | list(3); 107 | restore(); 108 | return; 109 | } 110 | 111 | if (expo == 0) 112 | { 113 | restore(); 114 | return; 115 | } 116 | 117 | push(BASE); 118 | bignum_power_number(expo); 119 | 120 | restore(); 121 | } 122 | 123 | #if SELFTEST 124 | 125 | void 126 | test_quickfactor(void) 127 | { 128 | int base, expo, i, j, h; 129 | logout("testing quickfactor\n"); 130 | for (i = 2; i < 10001; i++) { 131 | base = i; 132 | push_integer(base); 133 | push_integer(1); 134 | quickfactor(); 135 | h = tos; 136 | j = 0; 137 | while (base > 1) { 138 | expo = 0; 139 | while (base % primetab[j] == 0) { 140 | base /= primetab[j]; 141 | expo++; 142 | } 143 | if (expo) { 144 | push_integer(primetab[j]); 145 | push_integer(expo); 146 | quickpower(); 147 | } 148 | j++; 149 | } 150 | multiply_all(tos - h); 151 | p2 = pop(); 152 | p1 = pop(); 153 | if (!equal(p1, p2)) { 154 | logout("failed\n"); 155 | print_lisp(p1); 156 | print_lisp(p2); 157 | errout(); 158 | } 159 | } 160 | logout("ok\n"); 161 | } 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /Eigenmath/Sources/quotient.cpp: -------------------------------------------------------------------------------- 1 | // Divide polynomials 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_quotient(void) 7 | { 8 | push(cadr(p1)); // 1st arg, p(x) 9 | eval(); 10 | 11 | push(caddr(p1)); // 2nd arg, q(x) 12 | eval(); 13 | 14 | push(cadddr(p1)); // 3rd arg, x 15 | eval(); 16 | 17 | p1 = pop(); // default x 18 | if (p1 == symbol(NIL)) 19 | p1 = symbol(SYMBOL_X); 20 | push(p1); 21 | 22 | divpoly(); 23 | } 24 | 25 | //----------------------------------------------------------------------------- 26 | // 27 | // Divide polynomials 28 | // 29 | // Input: tos-3 Dividend 30 | // 31 | // tos-2 Divisor 32 | // 33 | // tos-1 x 34 | // 35 | // Output: tos-1 Quotient 36 | // 37 | //----------------------------------------------------------------------------- 38 | 39 | #define DIVIDEND p1 40 | #define DIVISOR p2 41 | #define X p3 42 | #define Q p4 43 | #define QUOTIENT p5 44 | 45 | void 46 | divpoly(void) 47 | { 48 | int h, i, m, n, x; 49 | U **dividend, **divisor; 50 | 51 | save(); 52 | 53 | X = pop(); 54 | DIVISOR = pop(); 55 | DIVIDEND = pop(); 56 | 57 | h = tos; 58 | 59 | dividend = stack + tos; 60 | 61 | push(DIVIDEND); 62 | push(X); 63 | m = coeff() - 1; // m is dividend's power 64 | 65 | divisor = stack + tos; 66 | 67 | push(DIVISOR); 68 | push(X); 69 | n = coeff() - 1; // n is divisor's power 70 | 71 | x = m - n; 72 | 73 | push_integer(0); 74 | QUOTIENT = pop(); 75 | 76 | while (x >= 0) 77 | { 78 | 79 | push(dividend[m]); 80 | push(divisor[n]); 81 | divide(); 82 | Q = pop(); 83 | 84 | for (i = 0; i <= n; i++) 85 | { 86 | push(dividend[x + i]); 87 | push(divisor[i]); 88 | push(Q); 89 | multiply(); 90 | subtract(); 91 | dividend[x + i] = pop(); 92 | } 93 | 94 | push(QUOTIENT); 95 | push(Q); 96 | push(X); 97 | push_integer(x); 98 | power(); 99 | multiply(); 100 | add(); 101 | QUOTIENT = pop(); 102 | 103 | m--; 104 | x--; 105 | } 106 | 107 | tos = h; 108 | 109 | push(QUOTIENT); 110 | 111 | restore(); 112 | } 113 | 114 | #if SELFTEST 115 | 116 | static char *s[] = { 117 | 118 | "quotient(x^2+1,x+1)-x+1", 119 | "0", 120 | 121 | "quotient(a*x^2+b*x+c,d*x+e)-(-a*e/(d^2)+a*x/d+b/d)", 122 | "0", 123 | }; 124 | 125 | void 126 | test_quotient(void) 127 | { 128 | test(__FILE__, s, sizeof s / sizeof (char *)); 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /Eigenmath/Sources/real.cpp: -------------------------------------------------------------------------------- 1 | /* Returns the real part of complex z 2 | 3 | z real(z) 4 | - ------- 5 | 6 | a + i b a 7 | 8 | exp(i a) cos(a) 9 | */ 10 | 11 | #include "../Headers/defs.h" 12 | 13 | void 14 | eval_real(void) 15 | { 16 | push(cadr(p1)); 17 | eval(); 18 | real(); 19 | } 20 | 21 | void 22 | real(void) 23 | { 24 | save(); 25 | rect(); 26 | p1 = pop(); 27 | push(p1); 28 | push(p1); 29 | conjugate(); 30 | add(); 31 | push_integer(2); 32 | divide(); 33 | restore(); 34 | } 35 | 36 | #if SELFTEST 37 | 38 | static char *s[] = { 39 | 40 | "real(a+i*b)", 41 | "a", 42 | 43 | "real(1+exp(i*pi/3))", 44 | "3/2", 45 | 46 | "real(i)", 47 | "0", 48 | 49 | "real((-1)^(1/3))", 50 | "1/2", 51 | }; 52 | 53 | void 54 | test_real(void) 55 | { 56 | test(__FILE__, s, sizeof s / sizeof (char *)); 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /Eigenmath/Sources/rect.cpp: -------------------------------------------------------------------------------- 1 | /* Convert complex z to rectangular form 2 | 3 | Input: push z 4 | 5 | Output: Result on stack 6 | */ 7 | 8 | #include "../Headers/defs.h" 9 | 10 | void 11 | eval_rect(void) 12 | { 13 | push(cadr(p1)); 14 | eval(); 15 | rect(); 16 | } 17 | 18 | void 19 | rect(void) 20 | { 21 | save(); 22 | p1 = pop(); 23 | if (car(p1) == symbol(ADD)) 24 | { 25 | push_integer(0); 26 | p1 = cdr(p1); 27 | while (iscons(p1)) 28 | { 29 | push(car(p1)); 30 | rect(); 31 | add(); 32 | p1 = cdr(p1); 33 | } 34 | } 35 | else 36 | { 37 | push(p1); // mag(z) * (cos(arg(z)) + i sin(arg(z))) 38 | mag(); 39 | push(p1); 40 | arg(); 41 | p1 = pop(); 42 | push(p1); 43 | cosine(); 44 | push(imaginaryunit); 45 | push(p1); 46 | sine(); 47 | multiply(); 48 | add(); 49 | multiply(); 50 | } 51 | restore(); 52 | } 53 | 54 | #if SELFTEST 55 | 56 | static char *s[] = { 57 | 58 | "rect(a+i*b)", 59 | "a+i*b", 60 | 61 | "rect(exp(a+i*b))", 62 | "i*exp(a)*sin(b)+exp(a)*cos(b)", 63 | 64 | "rect(1+exp(i*pi/3))", 65 | "3/2+1/2*i*3^(1/2)", 66 | 67 | "z=(a+b*i)/(c+d*i)", 68 | "", 69 | 70 | "rect(z)-real(z)-i*imag(z)", 71 | "0", 72 | 73 | "z=quote(z)", 74 | "", 75 | }; 76 | 77 | void 78 | test_rect(void) 79 | { 80 | test(__FILE__, s, sizeof s / sizeof (char *)); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /Eigenmath/Sources/rewrite.cpp: -------------------------------------------------------------------------------- 1 | // Rewrite by expanding all symbols 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | rewrite(void) 7 | { 8 | int h; 9 | save(); 10 | 11 | p1 = pop(); 12 | 13 | if (istensor(p1)) 14 | { 15 | rewrite_tensor(); 16 | restore(); 17 | return; 18 | } 19 | 20 | if (iscons(p1)) 21 | { 22 | h = tos; 23 | push(car(p1)); // Do not rewrite function name 24 | p1 = cdr(p1); 25 | while (iscons(p1)) 26 | { 27 | push(car(p1)); 28 | rewrite(); 29 | p1 = cdr(p1); 30 | } 31 | list(tos - h); 32 | restore(); 33 | return; 34 | } 35 | 36 | // If not a symbol then done 37 | 38 | if (!issymbol(p1)) 39 | { 40 | push(p1); 41 | restore(); 42 | return; 43 | } 44 | 45 | // Get the symbol's binding, try again 46 | 47 | p2 = get_binding(p1); 48 | push(p2); 49 | if (p1 != p2) 50 | rewrite(); 51 | 52 | restore(); 53 | } 54 | 55 | void 56 | rewrite_tensor(void) 57 | { 58 | int i; 59 | push(p1); 60 | copy_tensor(); 61 | p1 = pop(); 62 | for (i = 0; i < p1->u.tensor->nelem; i++) 63 | { 64 | push(p1->u.tensor->elem[i]); 65 | rewrite(); 66 | p1->u.tensor->elem[i] = pop(); 67 | } 68 | push(p1); 69 | } 70 | -------------------------------------------------------------------------------- /Eigenmath/Sources/run.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | jmp_buf stop_return, draw_stop_return; 5 | 6 | void 7 | stop(char *s) 8 | { 9 | if (draw_flag == 2) 10 | longjmp(draw_stop_return, 1); 11 | else 12 | { 13 | printstr("Stop: "); 14 | printstr(s); 15 | //printstr("\n"); 16 | longjmp(stop_return, 1); 17 | } 18 | } 19 | 20 | void 21 | run(char *s) 22 | { 23 | int i, n; 24 | 25 | if (strncmp(s, "selftest", 8) == 0) 26 | { 27 | selftest(); 28 | return; 29 | } 30 | 31 | if (setjmp(stop_return)) 32 | return; 33 | 34 | init(); 35 | 36 | while (1) 37 | { 38 | 39 | n = scan(s); 40 | 41 | p1 = pop(); 42 | check_stack(); 43 | 44 | if (n == 0) 45 | break; 46 | 47 | // if debug mode then print the source text 48 | 49 | if (equaln(get_binding(symbol(TRACE)), 1)) 50 | { 51 | for (i = 0; i < n; i++) 52 | if (s[i] != '\r' && s[i] != '\n') 53 | printchar(s[i]); 54 | /* 55 | if (s[n - 1] != '\n') // n is not zero, see above 56 | printchar('\n'); 57 | */ 58 | } 59 | 60 | s += n; 61 | 62 | push(p1); 63 | top_level_eval(); 64 | 65 | p2 = pop(); 66 | check_stack(); 67 | 68 | if (p2 == symbol(NIL)) 69 | continue; 70 | 71 | // print string w/o quotes 72 | 73 | if (isstr(p2)) 74 | { 75 | printstr(p2->u.str); 76 | //printstr("\n"); 77 | continue; 78 | } 79 | 80 | //if (equaln(get_binding(symbol(TTY)), 1) || test_flag) // tty mode? 81 | printline(p2); 82 | //else 83 | //{ 84 | // display(p2); 85 | //} 86 | } 87 | } 88 | 89 | void 90 | check_stack(void) 91 | { 92 | if (tos != 0) 93 | stop("stack error"); 94 | if (frame != stack + TOS) 95 | stop("frame error"); 96 | } 97 | 98 | // cannot reference symbols yet 99 | 100 | void 101 | echo_input(char *s) 102 | { 103 | printstr(s); 104 | //printstr("\n"); 105 | } 106 | 107 | // returns nil on stack if no result to print 108 | 109 | void 110 | top_level_eval(void) 111 | { 112 | save(); 113 | 114 | trigmode = 0; 115 | 116 | p1 = symbol(AUTOEXPAND); 117 | 118 | if (iszero(get_binding(p1))) 119 | expanding = 0; 120 | else 121 | expanding = 1; 122 | 123 | p1 = pop(); 124 | push(p1); 125 | eval(); 126 | p2 = pop(); 127 | 128 | // "draw", "for" and "setq" return "nil", there is no result to print 129 | 130 | if (p2 == symbol(NIL)) 131 | { 132 | push(p2); 133 | restore(); 134 | return; 135 | } 136 | 137 | // update "last" 138 | 139 | set_binding(symbol(LAST), p2); 140 | 141 | if (!iszero(get_binding(symbol(BAKE)))) 142 | { 143 | push(p2); 144 | bake(); 145 | p2 = pop(); 146 | } 147 | 148 | // If we evaluated the symbol "i" or "j" and the result was sqrt(-1) 149 | 150 | // then don't do anything. 151 | 152 | // Otherwise if "j" is an imaginary unit then subst. 153 | 154 | // Otherwise if "i" is an imaginary unit then subst. 155 | 156 | if ((p1 == symbol(SYMBOL_I) || p1 == symbol(SYMBOL_J)) 157 | && isimaginaryunit(p2)); 158 | else if (isimaginaryunit(get_binding(symbol(SYMBOL_J)))) 159 | { 160 | push(p2); 161 | push(imaginaryunit); 162 | push_symbol(SYMBOL_J); 163 | subst(); 164 | p2 = pop(); 165 | } 166 | else if (isimaginaryunit(get_binding(symbol(SYMBOL_I)))) 167 | { 168 | push(p2); 169 | push(imaginaryunit); 170 | push_symbol(SYMBOL_I); 171 | subst(); 172 | p2 = pop(); 173 | } 174 | 175 | #ifndef LINUX 176 | 177 | // if we evaluated the symbol "a" and got "b" then print "a=b" 178 | 179 | // do not print "a=a" 180 | 181 | if (issymbol(p1) && !iskeyword(p1) && p1 != p2 && test_flag == 0) 182 | { 183 | push_symbol(SETQ); 184 | push(p1); 185 | push(p2); 186 | list(3); 187 | p2 = pop(); 188 | } 189 | #endif 190 | push(p2); 191 | 192 | restore(); 193 | } 194 | 195 | void 196 | check_esc_flag(void) 197 | { 198 | if (esc_flag) 199 | stop("esc key"); 200 | } 201 | -------------------------------------------------------------------------------- /Eigenmath/Sources/selftest.cpp: -------------------------------------------------------------------------------- 1 | // self test functions 2 | 3 | #include "../Headers/defs.h" 4 | 5 | static jmp_buf jbuf; 6 | 7 | void 8 | selftest(void) 9 | { 10 | // for handling "errout" 11 | 12 | if (setjmp(jbuf)) 13 | return; 14 | 15 | mini_test(); 16 | 17 | logout("OK, all tests passed.\n"); 18 | } 19 | 20 | void 21 | logout(char *s) 22 | { 23 | printstr(s); 24 | } 25 | 26 | void 27 | errout(void) 28 | { 29 | logout("\n"); 30 | longjmp(jbuf, 1); 31 | } 32 | 33 | void 34 | test(char *file, char **s, int n) 35 | { 36 | 37 | } 38 | 39 | // these tests do not use "run" but still need a "stop" context 40 | 41 | extern jmp_buf stop_return; 42 | 43 | void 44 | test_low_level(void) 45 | { 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Eigenmath/Sources/sgn.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Author : philippe.billet@noos.fr 4 | // 5 | // sgn sign function 6 | // 7 | // 8 | //----------------------------------------------------------------------------- 9 | 10 | #include "../Headers/defs.h" 11 | 12 | void 13 | eval_sgn(void) 14 | { 15 | push(cadr(p1)); 16 | eval(); 17 | sgn(); 18 | } 19 | 20 | void 21 | sgn(void) 22 | { 23 | save(); 24 | yysgn(); 25 | restore(); 26 | } 27 | 28 | #define X p1 29 | 30 | void 31 | yysgn(void) 32 | { 33 | 34 | X = pop(); 35 | 36 | if (isdouble(p1)) 37 | { 38 | if (p1->u.d > 0) 39 | { 40 | push_integer(1); 41 | return; 42 | } 43 | else if (p1->u.d == 0) 44 | { 45 | push_integer(1); 46 | return; 47 | } 48 | else 49 | { 50 | push_integer(-1); 51 | return; 52 | } 53 | } 54 | 55 | if (isrational(p1)) 56 | { 57 | if (MSIGN(mmul(p1->u.q.a, p1->u.q.b)) == -1) 58 | { 59 | push_integer(-1); 60 | return; 61 | } 62 | else if (MZERO(mmul(p1->u.q.a, p1->u.q.b))) 63 | { 64 | push_integer(0); 65 | return; 66 | } 67 | else 68 | { 69 | push_integer(1); 70 | return; 71 | } 72 | } 73 | 74 | if (iscomplexnumber(X)) 75 | { 76 | push_integer(-1); 77 | push(X); 78 | absval(); 79 | power(); 80 | push(X); 81 | multiply(); 82 | return; 83 | } 84 | 85 | if (isnegativeterm(X)) 86 | { 87 | push_symbol(SGN); 88 | push(X); 89 | negate(); 90 | list(2); 91 | push_integer(-1); 92 | multiply(); 93 | return; 94 | } 95 | 96 | /* push_integer(2); 97 | push(X); 98 | heaviside(); 99 | multiply(); 100 | push_integer(-1); 101 | add(); */ 102 | 103 | push_symbol(SGN); 104 | push(X); 105 | list(2); 106 | } 107 | 108 | #if SELFTEST 109 | 110 | static char *s[] = { 111 | 112 | 113 | "sgn(-3)", 114 | "-1", 115 | 116 | 117 | "sgn(0)", 118 | "0", 119 | 120 | "sgn(3)", 121 | "1", 122 | 123 | }; 124 | 125 | void 126 | test_sgn(void) 127 | { 128 | test(__FILE__, s, sizeof s / sizeof (char *)); 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /Eigenmath/Sources/sinh.cpp: -------------------------------------------------------------------------------- 1 | // exp(x) - exp(-x) 2 | // sinh(x) = ---------------- 3 | // 2 4 | 5 | #include "../Headers/defs.h" 6 | 7 | void 8 | eval_sinh(void) 9 | { 10 | push(cadr(p1)); 11 | eval(); 12 | ysinh(); 13 | } 14 | 15 | void 16 | ysinh(void) 17 | { 18 | save(); 19 | yysinh(); 20 | restore(); 21 | } 22 | 23 | void 24 | yysinh(void) 25 | { 26 | double d; 27 | p1 = pop(); 28 | if (car(p1) == symbol(ARCSINH)) 29 | { 30 | push(cadr(p1)); 31 | return; 32 | } 33 | if (isdouble(p1)) 34 | { 35 | d = sinh(p1->u.d); 36 | if (fabs(d) < 1e-10) 37 | d = 0.0; 38 | push_double(d); 39 | return; 40 | } 41 | if (iszero(p1)) 42 | { 43 | push(zero); 44 | return; 45 | } 46 | push_symbol(SINH); 47 | push(p1); 48 | list(2); 49 | } 50 | 51 | #if SELFTEST 52 | 53 | static char *s[] = { 54 | 55 | "sinh(x)", 56 | "sinh(x)", 57 | 58 | "sinh(0)", 59 | "0", 60 | 61 | "sinh(arcsinh(x))", 62 | "x", 63 | }; 64 | 65 | void 66 | test_sinh(void) 67 | { 68 | test(__FILE__, s, sizeof s / sizeof (char *)); 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /Eigenmath/Sources/stack.cpp: -------------------------------------------------------------------------------- 1 | // _______ 2 | // | | <- stack 3 | // | | 4 | // |_______| 5 | // | | <- stack + tos 6 | // | | 7 | // | | 8 | // |_______| 9 | // | | <- frame 10 | // |_______| 11 | // <- stack + TOS 12 | // 13 | // The stack grows from low memory towards high memory. This is so that 14 | // multiple expressions can be pushed on the stack and then accessed as an 15 | // array. 16 | // 17 | // The frame area holds local variables and grows from high memory towards 18 | // low memory. The frame area makes local variables visible to the garbage 19 | // collector. 20 | 21 | #include "../Headers/defs.h" 22 | 23 | U **frame, *stack[TOS]; 24 | int tos; 25 | 26 | void 27 | push(U *p) 28 | { 29 | if (stack + tos >= frame) 30 | stop("stack overflow"); 31 | stack[tos++] = p; 32 | } 33 | 34 | U * 35 | pop() 36 | { 37 | if (tos == 0) 38 | stop("stack underflow"); 39 | return stack[--tos]; 40 | } 41 | 42 | void 43 | push_frame(int n) 44 | { 45 | int i; 46 | frame -= n; 47 | if (frame < stack + tos) 48 | stop("frame overflow, circular reference?"); 49 | for (i = 0; i < n; i++) 50 | frame[i] = symbol(NIL); 51 | } 52 | 53 | void 54 | pop_frame(int n) 55 | { 56 | frame += n; 57 | if (frame > stack + TOS) 58 | stop("frame underflow"); 59 | } 60 | 61 | void 62 | save(void) 63 | { 64 | frame -= 10; 65 | if (frame < stack + tos) 66 | stop("frame overflow, circular reference?"); 67 | frame[0] = p0; 68 | frame[1] = p1; 69 | frame[2] = p2; 70 | frame[3] = p3; 71 | frame[4] = p4; 72 | frame[5] = p5; 73 | frame[6] = p6; 74 | frame[7] = p7; 75 | frame[8] = p8; 76 | frame[9] = p9; 77 | } 78 | 79 | void 80 | restore(void) 81 | { 82 | if (frame > stack + TOS - 10) 83 | stop("frame underflow"); 84 | p0 = frame[0]; 85 | p1 = frame[1]; 86 | p2 = frame[2]; 87 | p3 = frame[3]; 88 | p4 = frame[4]; 89 | p5 = frame[5]; 90 | p6 = frame[6]; 91 | p7 = frame[7]; 92 | p8 = frame[8]; 93 | p9 = frame[9]; 94 | frame += 10; 95 | } 96 | 97 | // Local U * is OK here because there is no functional path to the garbage collector. 98 | 99 | void 100 | swap(void) 101 | { 102 | U *p, *q; 103 | p = pop(); 104 | q = pop(); 105 | push(p); 106 | push(q); 107 | } 108 | 109 | // Local U * is OK here because there is no functional path to the garbage collector. 110 | 111 | void 112 | dupl(void) 113 | { 114 | U *p; 115 | p = pop(); 116 | push(p); 117 | push(p); 118 | } 119 | -------------------------------------------------------------------------------- /Eigenmath/Sources/subst.cpp: -------------------------------------------------------------------------------- 1 | /* Substitute new expr for old expr in expr. 2 | 3 | Input: push expr 4 | 5 | push old expr 6 | 7 | push new expr 8 | 9 | Output: Result on stack 10 | */ 11 | 12 | #include "../Headers/defs.h" 13 | 14 | void 15 | subst(void) 16 | { 17 | int i; 18 | save(); 19 | p3 = pop(); // new expr 20 | p2 = pop(); // old expr 21 | if (p2 == symbol(NIL) || p3 == symbol(NIL)) 22 | { 23 | restore(); 24 | return; 25 | } 26 | p1 = pop(); // expr 27 | if (istensor(p1)) 28 | { 29 | p4 = alloc_tensor(p1->u.tensor->nelem); 30 | p4->u.tensor->ndim = p1->u.tensor->ndim; 31 | for (i = 0; i < p1->u.tensor->ndim; i++) 32 | p4->u.tensor->dim[i] = p1->u.tensor->dim[i]; 33 | for (i = 0; i < p1->u.tensor->nelem; i++) 34 | { 35 | push(p1->u.tensor->elem[i]); 36 | push(p2); 37 | push(p3); 38 | subst(); 39 | p4->u.tensor->elem[i] = pop(); 40 | } 41 | push(p4); 42 | } 43 | else if (equal(p1, p2)) 44 | push(p3); 45 | else if (iscons(p1)) 46 | { 47 | push(car(p1)); 48 | push(p2); 49 | push(p3); 50 | subst(); 51 | push(cdr(p1)); 52 | push(p2); 53 | push(p3); 54 | subst(); 55 | cons(); 56 | } 57 | else 58 | push(p1); 59 | restore(); 60 | } 61 | -------------------------------------------------------------------------------- /Eigenmath/Sources/sum.cpp: -------------------------------------------------------------------------------- 1 | // 'sum' function 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define A p3 6 | #define B p4 7 | #define I p5 8 | #define X p6 9 | 10 | void 11 | eval_sum(void) 12 | { 13 | int i, j, k; 14 | 15 | // 1st arg (quoted) 16 | 17 | X = cadr(p1); 18 | if (!issymbol(X)) 19 | stop("sum: 1st arg?"); 20 | 21 | // 2nd arg 22 | 23 | push(caddr(p1)); 24 | eval(); 25 | j = pop_integer(); 26 | if (j == (int)0x80000000) 27 | stop("sum: 2nd arg?"); 28 | 29 | // 3rd arg 30 | 31 | push(cadddr(p1)); 32 | eval(); 33 | k = pop_integer(); 34 | if (k == (int)0x80000000) 35 | stop("sum: 3rd arg?"); 36 | 37 | // 4th arg 38 | 39 | p1 = caddddr(p1); 40 | 41 | B = get_binding(X); 42 | A = get_arglist(X); 43 | 44 | push_integer(0); 45 | 46 | for (i = j; i <= k; i++) 47 | { 48 | push_integer(i); 49 | I = pop(); 50 | set_binding(X, I); 51 | push(p1); 52 | eval(); 53 | add(); 54 | } 55 | 56 | set_binding_and_arglist(X, B, A); 57 | } 58 | -------------------------------------------------------------------------------- /Eigenmath/Sources/symbol.cpp: -------------------------------------------------------------------------------- 1 | // The symbol table is a simple array of struct U. 2 | 3 | #include "../Headers/defs.h" 4 | 5 | // put symbol at index n 6 | 7 | void 8 | std_symbol(char *s, int n) 9 | { 10 | U *p; 11 | p = symtab + n; 12 | p->u.printname = s; 13 | } 14 | 15 | // symbol lookup, create symbol if need be 16 | 17 | U * 18 | usr_symbol(char *s) 19 | { 20 | int i; 21 | U *p; 22 | for (i = 0; i < NSYM; i++) 23 | { 24 | if (symtab[i].u.printname == 0) 25 | break; 26 | if (strcmp(s, symtab[i].u.printname) == 0) 27 | return symtab + i; 28 | } 29 | if (i == NSYM) 30 | stop("symbol table overflow"); 31 | p = symtab + i; 32 | p->u.printname = strdup(s); 33 | return p; 34 | } 35 | 36 | // get the symbol's printname 37 | 38 | char * 39 | get_printname(U *p) 40 | { 41 | if (p->k != SYM) 42 | stop("symbol error"); 43 | return p->u.printname; 44 | } 45 | 46 | // clears the arglist too 47 | 48 | void 49 | set_binding(U *p, U *q) 50 | { 51 | if (p->k != SYM) 52 | stop("symbol error"); 53 | binding[p - symtab] = q; 54 | arglist[p - symtab] = symbol(NIL); 55 | } 56 | 57 | U * 58 | get_binding(U *p) 59 | { 60 | if (p->k != SYM) 61 | stop("symbol error"); 62 | return binding[p - symtab]; 63 | } 64 | 65 | void 66 | set_binding_and_arglist(U *p, U *q, U *r) 67 | { 68 | if (p->k != SYM) 69 | stop("symbol error"); 70 | binding[p - symtab] = q; 71 | arglist[p - symtab] = r; 72 | } 73 | 74 | U * 75 | get_arglist(U *p) 76 | { 77 | if (p->k != SYM) 78 | stop("symbol error"); 79 | return arglist[p - symtab]; 80 | } 81 | 82 | // get symbol's number from ptr 83 | 84 | int 85 | symnum(U *p) 86 | { 87 | if (p->k != SYM) 88 | stop("symbol error"); 89 | return (int)(p - symtab); 90 | } 91 | 92 | // push indexed symbol 93 | 94 | void 95 | push_symbol(int k) 96 | { 97 | push(symtab + k); 98 | } 99 | 100 | void 101 | clear_symbols(void) 102 | { 103 | int i; 104 | for (i = 0; i < NSYM; i++) 105 | { 106 | binding[i] = symtab + i; 107 | arglist[i] = symbol(NIL); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Eigenmath/Sources/tanh.cpp: -------------------------------------------------------------------------------- 1 | // exp(2 x) - 1 2 | // tanh(x) = -------------- 3 | // exp(2 x) + 1 4 | 5 | #include "../Headers/defs.h" 6 | 7 | void 8 | eval_tanh(void) 9 | { 10 | double d; 11 | push(cadr(p1)); 12 | eval(); 13 | p1 = pop(); 14 | if (car(p1) == symbol(ARCTANH)) 15 | { 16 | push(cadr(p1)); 17 | return; 18 | } 19 | if (isdouble(p1)) 20 | { 21 | d = tanh(p1->u.d); 22 | if (fabs(d) < 1e-10) 23 | d = 0.0; 24 | push_double(d); 25 | return; 26 | } 27 | if (iszero(p1)) 28 | { 29 | push(zero); 30 | return; 31 | } 32 | push_symbol(TANH); 33 | push(p1); 34 | list(2); 35 | } 36 | 37 | #if SELFTEST 38 | 39 | static char *s[] = { 40 | 41 | "tanh(x)", 42 | "tanh(x)", 43 | 44 | "tanh(0)", 45 | "0", 46 | 47 | "tanh(arctanh(x))", 48 | "x", 49 | }; 50 | 51 | void 52 | test_tanh(void) 53 | { 54 | test(__FILE__, s, sizeof s / sizeof (char *)); 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /Eigenmath/Sources/taylor.cpp: -------------------------------------------------------------------------------- 1 | /* Taylor expansion of a function 2 | 3 | push(F) 4 | push(X) 5 | push(N) 6 | push(A) 7 | taylor() 8 | */ 9 | 10 | #include "../Headers/defs.h" 11 | 12 | void 13 | eval_taylor(void) 14 | { 15 | // 1st arg 16 | 17 | p1 = cdr(p1); 18 | push(car(p1)); 19 | eval(); 20 | 21 | // 2nd arg 22 | 23 | p1 = cdr(p1); 24 | push(car(p1)); 25 | eval(); 26 | p2 = pop(); 27 | if (p2 == symbol(NIL)) 28 | guess(); 29 | else 30 | push(p2); 31 | 32 | // 3rd arg 33 | 34 | p1 = cdr(p1); 35 | push(car(p1)); 36 | eval(); 37 | p2 = pop(); 38 | if (p2 == symbol(NIL)) 39 | push_integer(24); // default number of terms 40 | else 41 | push(p2); 42 | 43 | // 4th arg 44 | 45 | p1 = cdr(p1); 46 | push(car(p1)); 47 | eval(); 48 | p2 = pop(); 49 | if (p2 == symbol(NIL)) 50 | push_integer(0); // default expansion point 51 | else 52 | push(p2); 53 | 54 | taylor(); 55 | } 56 | 57 | #define F p1 58 | #define X p2 59 | #define N p3 60 | #define A p4 61 | #define C p5 62 | 63 | void 64 | taylor(void) 65 | { 66 | int i, k; 67 | 68 | save(); 69 | 70 | A = pop(); 71 | N = pop(); 72 | X = pop(); 73 | F = pop(); 74 | 75 | push(N); 76 | k = pop_integer(); 77 | if (k == (int)0x80000000) 78 | { 79 | push_symbol(TAYLOR); 80 | push(F); 81 | push(X); 82 | push(N); 83 | push(A); 84 | list(5); 85 | restore(); 86 | return; 87 | } 88 | 89 | push(F); // f(a) 90 | push(X); 91 | push(A); 92 | subst(); 93 | eval(); 94 | 95 | push_integer(1); 96 | C = pop(); 97 | 98 | for (i = 1; i <= k; i++) 99 | { 100 | 101 | push(F); // f = f' 102 | push(X); 103 | derivative(); 104 | F = pop(); 105 | 106 | if (iszero(F)) 107 | break; 108 | 109 | push(C); // c = c * (x - a) 110 | push(X); 111 | push(A); 112 | subtract(); 113 | multiply(); 114 | C = pop(); 115 | 116 | push(F); // f(a) 117 | push(X); 118 | push(A); 119 | subst(); 120 | eval(); 121 | 122 | push(C); 123 | multiply(); 124 | push_integer(i); 125 | factorial(); 126 | divide(); 127 | 128 | add(); 129 | } 130 | 131 | restore(); 132 | } 133 | 134 | #if SELFTEST 135 | 136 | static char *s[] = { 137 | 138 | "taylor(1/(5+4*cos(x)),x,6,0)-(1/9+2/81*x^2+5/1458*x^4+49/131220*x^6)", 139 | "0", 140 | 141 | "taylor(1/(5+4*cos(x)),x,6)-(1/9+2/81*x^2+5/1458*x^4+49/131220*x^6)", 142 | "0", 143 | }; 144 | 145 | void 146 | test_taylor(void) 147 | { 148 | test(__FILE__, s, sizeof s / sizeof (char *)); 149 | } 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /Eigenmath/Sources/transform.cpp: -------------------------------------------------------------------------------- 1 | /* Transform an expression using table look-up 2 | 3 | The expression and free variable are on the stack. 4 | 5 | The argument s is a null terminated list of transform rules. 6 | 7 | For example, see itab.cpp 8 | 9 | Internally, the following symbols are used: 10 | 11 | F input expression 12 | 13 | X free variable, i.e. F of X 14 | 15 | A template expression 16 | 17 | B result expression 18 | 19 | C list of conditional expressions 20 | */ 21 | 22 | #include "../Headers/defs.h" 23 | 24 | // p1 and p2 are tmps 25 | 26 | #define F p3 27 | #define X p4 28 | #define A p5 29 | #define B p6 30 | #define C p7 31 | 32 | void 33 | transform(char **s) 34 | { 35 | int h; 36 | 37 | save(); 38 | 39 | X = pop(); 40 | F = pop(); 41 | 42 | // save symbol context in case eval(B) below calls transform 43 | 44 | push(get_binding(symbol(METAA))); 45 | push(get_binding(symbol(METAB))); 46 | push(get_binding(symbol(METAX))); 47 | 48 | set_binding(symbol(METAX), X); 49 | 50 | // put constants in F(X) on the stack 51 | 52 | h = tos; 53 | push_integer(1); 54 | push(F); 55 | push(X); 56 | polyform(); // collect coefficients of x, x^2, etc. 57 | push(X); 58 | decomp(); 59 | 60 | while (*s) 61 | { 62 | 63 | scan_meta(*s); 64 | p1 = pop(); 65 | 66 | A = cadr(p1); 67 | B = caddr(p1); 68 | C = cdddr(p1); 69 | 70 | if (f_equals_a(h)) 71 | break; 72 | 73 | s++; 74 | } 75 | 76 | tos = h; 77 | 78 | if (*s) 79 | { 80 | push(B); 81 | eval(); 82 | p1 = pop(); 83 | } 84 | else 85 | p1 = symbol(NIL); 86 | 87 | set_binding(symbol(METAX), pop()); 88 | set_binding(symbol(METAB), pop()); 89 | set_binding(symbol(METAA), pop()); 90 | 91 | push(p1); 92 | 93 | restore(); 94 | } 95 | 96 | // search for a METAA and METAB such that F = A 97 | 98 | int 99 | f_equals_a(int h) 100 | { 101 | int i, j; 102 | for (i = h; i < tos; i++) 103 | { 104 | set_binding(symbol(METAA), stack[i]); 105 | for (j = h; j < tos; j++) 106 | { 107 | set_binding(symbol(METAB), stack[j]); 108 | p1 = C; // are conditions ok? 109 | while (iscons(p1)) 110 | { 111 | push(car(p1)); 112 | eval(); 113 | p2 = pop(); 114 | if (iszero(p2)) 115 | break; 116 | p1 = cdr(p1); 117 | } 118 | if (iscons(p1)) // no, try next j 119 | continue; 120 | push(F); // F = A? 121 | push(A); 122 | eval(); 123 | subtract(); 124 | p1 = pop(); 125 | if (iszero(p1)) 126 | return 1; // yes 127 | } 128 | } 129 | return 0; // no 130 | } 131 | -------------------------------------------------------------------------------- /Eigenmath/Sources/transpose.cpp: -------------------------------------------------------------------------------- 1 | // Transpose tensor indices 2 | 3 | #include "../Headers/defs.h" 4 | 5 | void 6 | eval_transpose(void) 7 | { 8 | push(cadr(p1)); 9 | eval(); 10 | if (cddr(p1) == symbol(NIL)) 11 | { 12 | push_integer(1); 13 | push_integer(2); 14 | } 15 | else 16 | { 17 | push(caddr(p1)); 18 | eval(); 19 | push(cadddr(p1)); 20 | eval(); 21 | } 22 | transpose(); 23 | } 24 | 25 | void 26 | transpose(void) 27 | { 28 | int i, j, k, l, m, ndim, nelem, t; 29 | int ai[MAXDIM], an[MAXDIM]; 30 | U **a, **b; 31 | 32 | save(); 33 | 34 | p3 = pop(); 35 | p2 = pop(); 36 | p1 = pop(); 37 | 38 | if (!istensor(p1)) 39 | { 40 | if (!iszero(p1)) 41 | stop("transpose: tensor expected, 1st arg is not a tensor"); 42 | push(zero); 43 | restore(); 44 | return; 45 | } 46 | 47 | ndim = p1->u.tensor->ndim; 48 | nelem = p1->u.tensor->nelem; 49 | 50 | // vector? 51 | 52 | if (ndim == 1) 53 | { 54 | push(p1); 55 | restore(); 56 | return; 57 | } 58 | 59 | push(p2); 60 | l = pop_integer(); 61 | 62 | push(p3); 63 | m = pop_integer(); 64 | 65 | if (l < 1 || l > ndim || m < 1 || m > ndim) 66 | stop("transpose: index out of range"); 67 | 68 | l--; 69 | m--; 70 | 71 | p2 = alloc_tensor(nelem); 72 | 73 | p2->u.tensor->ndim = ndim; 74 | 75 | for (i = 0; i < ndim; i++) 76 | p2->u.tensor->dim[i] = p1->u.tensor->dim[i]; 77 | 78 | p2->u.tensor->dim[l] = p1->u.tensor->dim[m]; 79 | p2->u.tensor->dim[m] = p1->u.tensor->dim[l]; 80 | 81 | a = p1->u.tensor->elem; 82 | b = p2->u.tensor->elem; 83 | 84 | // init tensor index 85 | 86 | for (i = 0; i < ndim; i++) 87 | { 88 | ai[i] = 0; 89 | an[i] = p1->u.tensor->dim[i]; 90 | } 91 | 92 | // copy components from a to b 93 | 94 | for (i = 0; i < nelem; i++) 95 | { 96 | 97 | // swap indices l and m 98 | 99 | t = ai[l]; 100 | ai[l] = ai[m]; 101 | ai[m] = t; 102 | t = an[l]; 103 | an[l] = an[m]; 104 | an[m] = t; 105 | 106 | // convert tensor index to linear index k 107 | 108 | k = 0; 109 | for (j = 0; j < ndim; j++) 110 | k = (k * an[j]) + ai[j]; 111 | 112 | // swap indices back 113 | 114 | t = ai[l]; 115 | ai[l] = ai[m]; 116 | ai[m] = t; 117 | t = an[l]; 118 | an[l] = an[m]; 119 | an[m] = t; 120 | 121 | // copy one element 122 | 123 | b[k] = a[i]; 124 | 125 | // increment tensor index 126 | 127 | // Suppose the tensor dimensions are 2 and 3. 128 | // Then the tensor index ai increments as follows: 129 | // 00 -> 01 130 | // 01 -> 02 131 | // 02 -> 10 132 | // 10 -> 11 133 | // 11 -> 12 134 | // 12 -> 00 135 | 136 | for (j = ndim - 1; j >= 0; j--) 137 | { 138 | if (++ai[j] < an[j]) 139 | break; 140 | ai[j] = 0; 141 | } 142 | } 143 | 144 | push(p2); 145 | restore(); 146 | } 147 | 148 | #if SELFTEST 149 | 150 | static char *s[] = { 151 | 152 | "transpose(0)", 153 | "0", 154 | 155 | "transpose(0.0)", 156 | "0", 157 | 158 | "transpose(((a,b),(c,d)))", 159 | "((a,c),(b,d))", 160 | 161 | "transpose(((a,b),(c,d)),1,2)", 162 | "((a,c),(b,d))", 163 | 164 | "transpose(((a,b,c),(d,e,f)),1,2)", 165 | "((a,d),(b,e),(c,f))", 166 | 167 | "transpose(((a,d),(b,e),(c,f)),1,2)", 168 | "((a,b,c),(d,e,f))", 169 | 170 | "transpose((a,b,c))", 171 | "(a,b,c)", 172 | }; 173 | 174 | void 175 | test_transpose(void) 176 | { 177 | test(__FILE__, s, sizeof s / sizeof (char *)); 178 | } 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /Eigenmath/Sources/userfunc.cpp: -------------------------------------------------------------------------------- 1 | // Evaluate a user defined function 2 | 3 | #include "../Headers/defs.h" 4 | 5 | #define F p3 // F is the function body 6 | #define A p4 // A is the formal argument list 7 | #define B p5 // B is the calling argument list 8 | #define S p6 // S is the argument substitution list 9 | 10 | void 11 | eval_user_function(void) 12 | { 13 | int h; 14 | 15 | // Use "derivative" instead of "d" if there is no user function "d" 16 | 17 | if (car(p1) == symbol(SYMBOL_D) && get_arglist(symbol(SYMBOL_D)) == symbol(NIL)) 18 | { 19 | eval_derivative(); 20 | return; 21 | } 22 | 23 | F = get_binding(car(p1)); 24 | A = get_arglist(car(p1)); 25 | B = cdr(p1); 26 | 27 | // Undefined function? 28 | 29 | if (F == car(p1)) 30 | { 31 | h = tos; 32 | push(F); 33 | p1 = B; 34 | while (iscons(p1)) 35 | { 36 | push(car(p1)); 37 | eval(); 38 | p1 = cdr(p1); 39 | } 40 | list(tos - h); 41 | return; 42 | } 43 | 44 | // Create the argument substitution list S 45 | 46 | p1 = A; 47 | p2 = B; 48 | h = tos; 49 | while (iscons(p1) && iscons(p2)) 50 | { 51 | push(car(p1)); 52 | push(car(p2)); 53 | eval(); 54 | p1 = cdr(p1); 55 | p2 = cdr(p2); 56 | } 57 | list(tos - h); 58 | S = pop(); 59 | 60 | // Evaluate the function body 61 | 62 | push(F); 63 | if (iscons(S)) 64 | { 65 | push(S); 66 | rewrite_args(); 67 | } 68 | eval(); 69 | } 70 | 71 | // Rewrite by expanding symbols that contain args 72 | 73 | int 74 | rewrite_args(void) 75 | { 76 | int h, n = 0; 77 | save(); 78 | 79 | p2 = pop(); // subst. list 80 | p1 = pop(); // expr 81 | 82 | if (istensor(p1)) 83 | { 84 | n = rewrite_args_tensor(); 85 | restore(); 86 | return n; 87 | } 88 | 89 | if (iscons(p1)) 90 | { 91 | h = tos; 92 | push(car(p1)); // Do not rewrite function name 93 | p1 = cdr(p1); 94 | while (iscons(p1)) 95 | { 96 | push(car(p1)); 97 | push(p2); 98 | n += rewrite_args(); 99 | p1 = cdr(p1); 100 | } 101 | list(tos - h); 102 | restore(); 103 | return n; 104 | } 105 | 106 | // If not a symbol then done 107 | 108 | if (!issymbol(p1)) 109 | { 110 | push(p1); 111 | restore(); 112 | return 0; 113 | } 114 | 115 | // Try for an argument substitution first 116 | 117 | p3 = p2; 118 | while (iscons(p3)) 119 | { 120 | if (p1 == car(p3)) 121 | { 122 | push(cadr(p3)); 123 | restore(); 124 | return 1; 125 | } 126 | p3 = cddr(p3); 127 | } 128 | 129 | // Get the symbol's binding, try again 130 | 131 | p3 = get_binding(p1); 132 | push(p3); 133 | if (p1 != p3) 134 | { 135 | push(p2); // subst. list 136 | n = rewrite_args(); 137 | if (n == 0) 138 | { 139 | pop(); 140 | push(p1); // restore if not rewritten with arg 141 | } 142 | } 143 | 144 | restore(); 145 | return n; 146 | } 147 | 148 | int 149 | rewrite_args_tensor(void) 150 | { 151 | int i, n = 0; 152 | push(p1); 153 | copy_tensor(); 154 | p1 = pop(); 155 | for (i = 0; i < p1->u.tensor->nelem; i++) 156 | { 157 | push(p1->u.tensor->elem[i]); 158 | push(p2); 159 | n += rewrite_args(); 160 | p1->u.tensor->elem[i] = pop(); 161 | } 162 | push(p1); 163 | return n; 164 | } 165 | -------------------------------------------------------------------------------- /Eigenmath/Sources/variables.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Scan expr for vars, return in vector 4 | // 5 | // Input: Expression on stack 6 | // 7 | // Output: Vector 8 | // 9 | //----------------------------------------------------------------------------- 10 | 11 | #include "../Headers/defs.h" 12 | 13 | static void scan(U *); 14 | static int __cmp(const void *, const void *); 15 | static int h; 16 | 17 | void 18 | variables(void) 19 | { 20 | int i, n; 21 | save(); 22 | p1 = pop(); 23 | h = tos; 24 | scan(p1); 25 | n = tos - h; 26 | if (n > 1) 27 | qsort(stack + h, n, sizeof(U *), __cmp); 28 | p1 = alloc_tensor(n); 29 | p1->u.tensor->ndim = 1; 30 | p1->u.tensor->dim[0] = n; 31 | for (i = 0; i < n; i++) 32 | p1->u.tensor->elem[i] = stack[i]; 33 | tos = h; 34 | push(p1); 35 | restore(); 36 | } 37 | 38 | static void 39 | scan(U *p) 40 | { 41 | int i; 42 | if (iscons(p)) 43 | { 44 | p = cdr(p); 45 | while (iscons(p)) 46 | { 47 | scan(car(p)); 48 | p = cdr(p); 49 | } 50 | } 51 | else if (issymbol(p) && p != symbol(E)) 52 | { 53 | for (i = h; i < tos; i++) 54 | if (stack[i] == p) 55 | return; 56 | push(p); 57 | } 58 | } 59 | 60 | static int 61 | __cmp(const void *p1, const void *p2) 62 | { 63 | return cmp_expr(*((U **)p1), *((U **)p2)); 64 | } 65 | -------------------------------------------------------------------------------- /Eigenmath/Sources/vectorize.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | //----------------------------------------------------------------------------- 4 | // 5 | // Encapsulate stack values in a vector 6 | // 7 | // Input: n Number of values on stack 8 | // 9 | // tos-n Start of value 10 | // 11 | // Output: Vector on stack 12 | // 13 | //----------------------------------------------------------------------------- 14 | 15 | #include "../Headers/defs.h" 16 | 17 | void 18 | vectorize(int n) 19 | { 20 | int i; 21 | 22 | save(); 23 | 24 | p1 = alloc_tensor(n); 25 | 26 | p1->u.tensor->ndim = 1; 27 | p1->u.tensor->dim[0] = n; 28 | 29 | for (i = 0; i < n; i++) 30 | p1->u.tensor->elem[i] = stack[tos - n + i]; 31 | 32 | tos -= n; 33 | 34 | push(p1); 35 | 36 | restore(); 37 | } 38 | -------------------------------------------------------------------------------- /Eigenmath/Sources/zero.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Headers/defs.h" 3 | 4 | void 5 | eval_zero(void) 6 | { 7 | int i, k[MAXDIM], m, n; 8 | m = 1; 9 | n = 0; 10 | p2 = cdr(p1); 11 | while (iscons(p2)) 12 | { 13 | push(car(p2)); 14 | eval(); 15 | i = pop_integer(); 16 | if (i < 2) 17 | { 18 | push(zero); 19 | return; 20 | } 21 | m *= i; 22 | k[n++] = i; 23 | p2 = cdr(p2); 24 | } 25 | if (n == 0) 26 | { 27 | push(zero); 28 | return; 29 | } 30 | p1 = alloc_tensor(m); 31 | p1->u.tensor->ndim = n; 32 | for (i = 0; i < n; i++) 33 | p1->u.tensor->dim[i] = k[i]; 34 | push(p1); 35 | } 36 | 37 | #if SELFTEST 38 | 39 | static char *s[] = { 40 | 41 | "zero(2,2)", 42 | "((0,0),(0,0))", 43 | 44 | "zero(1,1)", 45 | "0", 46 | }; 47 | 48 | void 49 | test_zero(void) 50 | { 51 | test(__FILE__, s, sizeof s / sizeof (char *)); 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Console-fx 2 | Math I/O engine tailored for monochrome-screen devices. 3 | 4 | ## General 5 | 6 | ### Description 7 | Console-fx is a project aimed to make it possible to display mathematical formulas on monochrome screens beautifully. The 8 | project is written in pure C++ without using any other non-standard libraries, and is designed to be built on multi-platforms. 9 | 10 | ### Usage 11 | The engine is designed as a lib. You need to include it in you own programs, and note that you have to implement some 12 | platform-specific functions like displaying the contents in the VRAM to screen and detecting a key event. An example 13 | is provided in main.cpp, which uses GLFW for graphics and key processing, and integrates Eigenmath as it's calculation kernel. 14 | 15 | More detailed, a program using the engine should be like this: 16 | ``` 17 | // File main.cpp placed in the same directory as the folder "Console". 18 | 19 | // First you have to include standard library headers and the engine header. Generally only "console.h" is needed. 20 | #include 21 | #include "Console/Headers/console.h" 22 | 23 | // Main enterance for the program. 24 | int main(int argc, char *argv[]) 25 | { 26 | // Emulated VRAM. 27 | unsigned char vram[VRAM_SIZE_BYTE]; 28 | 29 | // New instance for class Console and a string as the input/output buffer. 30 | // Note that all classes, enums, etc., are under the namespace fx. 31 | fx::Console console(vram); 32 | fx::String buffer; 33 | 34 | // Function "ShouldExit()" need to be implemented by yourself. 35 | while (!ShouldExit()) 36 | { 37 | console.input(buffer); // Get input, and store it in buffer. 38 | std::cout << buffer.c_str() << std::endl; // Process the input. Here we just print it out. 39 | console.output(buffer); // Output the processed string. 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | ``` 46 | 47 | For even more information, the source code is always there. :-) 48 | 49 | ### Shots 50 | There are some screen shots when I run it on my Mac. 51 | 52 | Simple expressions go well. 53 | ![01](Shots/01.png) 54 | 55 | ... and also no problem with complex ones as follows. 56 | ![02](Shots/02.png) 57 | 58 | ## About 59 | 60 | ### License 61 | The program is a free software. You can do anything to it with non-commercial purpose. 62 | 63 | ### Contact 64 | Email: mango@live.cn 65 | 66 | Feel free to ask me any questions or propose any suggestions. 67 | 68 | -------------------------------------------------------------------------------- /Shots/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mike-Leo-Smith/Console-fx/a965a967b4411d3529fa8152d0cdc88b5e2be3b5/Shots/01.png -------------------------------------------------------------------------------- /Shots/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mike-Leo-Smith/Console-fx/a965a967b4411d3529fa8152d0cdc88b5e2be3b5/Shots/02.png -------------------------------------------------------------------------------- /Shots/on_calc.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mike-Leo-Smith/Console-fx/a965a967b4411d3529fa8152d0cdc88b5e2be3b5/Shots/on_calc.bmp -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /graphics.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Mike Smith on 2017/2/17. 3 | // 4 | 5 | #ifndef CONSOLE_FX_GRAPHICS_H 6 | #define CONSOLE_FX_GRAPHICS_H 7 | 8 | #include "glfw/glfw3.h" 9 | 10 | extern void DisplayVRAM(void); 11 | extern GLFWwindow *win; 12 | 13 | #endif //CONSOLE_FX_GRAPHICS_H 14 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Console/Headers/display.h" 4 | #include "Console/Headers/console.h" 5 | #include "Eigenmath/Headers/defs.h" 6 | 7 | GLFWwindow *win; 8 | const int scale = 2; 9 | unsigned char vram[VRAM_SIZE_BYTE]; 10 | 11 | void Init(void) 12 | { 13 | glfwInit(); 14 | win = glfwCreateWindow(SCREEN_WIDTH * scale, SCREEN_HEIGHT * scale, "Display", NULL, NULL); 15 | glfwMakeContextCurrent(win); 16 | glClearColor(1.0, 1.0, 1.0, 1.0); 17 | glTranslated(-1.0, 1.0, 0); 18 | glScaled(2.0 / SCREEN_WIDTH, -2.0 / SCREEN_HEIGHT, 1); 19 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 20 | glfwSetWindowSizeLimits(win, SCREEN_WIDTH * scale, SCREEN_HEIGHT * scale, SCREEN_WIDTH * scale, SCREEN_HEIGHT * scale); 21 | } 22 | 23 | inline void DrawPixel(int x, int y) 24 | { 25 | glColor3ub(0, 0, 0); 26 | glBegin(GL_QUADS); 27 | { 28 | glVertex2d(x, y); 29 | glVertex2d(x, y + 1); 30 | glVertex2d(x + 1, y + 1); 31 | glVertex2d(x + 1, y); 32 | } 33 | glEnd(); 34 | } 35 | 36 | inline void ClearPixel(int x, int y) 37 | { 38 | glColor3ub(235, 235, 235); 39 | glBegin(GL_QUADS); 40 | { 41 | glVertex2d(x, y); 42 | glVertex2d(x, y + 1); 43 | glVertex2d(x + 1, y + 1); 44 | glVertex2d(x + 1, y); 45 | } 46 | glEnd(); 47 | } 48 | 49 | void DisplayVRAM(void) 50 | { 51 | for (int x = 0; x < SCREEN_WIDTH; x++) 52 | { 53 | for (int y = 0; y < SCREEN_HEIGHT; y++) 54 | { 55 | (vram[(y * SCREEN_WIDTH_BYTE) + (x >> 3)] & (128 >> (x & 7))) ? DrawPixel(x, y) : ClearPixel(x, y); 56 | } 57 | } 58 | glFlush(); 59 | glfwSwapBuffers(win); 60 | if (glfwWindowShouldClose(win)) 61 | { 62 | glfwDestroyWindow(win); 63 | exit(0); 64 | } 65 | } 66 | 67 | fx::String io_buffer; 68 | fx::String calc_buffer; 69 | 70 | void printchar(int c) 71 | { 72 | calc_buffer.append((char)c); 73 | } 74 | 75 | void 76 | printstr(char *s) 77 | { 78 | calc_buffer.append(s); 79 | } 80 | 81 | int main() 82 | { 83 | fx::Console console(vram); 84 | Init(); 85 | const char *help_str[] = 86 | { 87 | "F1: ABS", 88 | "F2: DEF", 89 | "F3: FRA", 90 | "F4: INT", 91 | "F5: LOG", 92 | "F6: POW", 93 | "F7: PRO", 94 | "F8: ROO", 95 | "F9: SQR", 96 | "F10: STR", 97 | "F11: SUM", 98 | NULL 99 | }; 100 | 101 | for (int i = 0; help_str[i] != NULL; i++) 102 | { 103 | std::cout << help_str[i] << "\t"; 104 | } 105 | std::cout << std::endl; 106 | 107 | while (true) 108 | { 109 | console.input(io_buffer); 110 | calc_buffer.clear(); 111 | printf("io_buffer.c_str() = %s\n", io_buffer.c_str()); 112 | run((char *)io_buffer.c_str()); 113 | if (calc_buffer.c_str()[calc_buffer.size() - 1] == '\n') 114 | { 115 | calc_buffer.backspace(); 116 | } 117 | console.output(calc_buffer); 118 | } 119 | } --------------------------------------------------------------------------------