├── .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 | 
54 |
55 | ... and also no problem with complex ones as follows.
56 | 
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 | }
--------------------------------------------------------------------------------