1 
2 /*
3  *  Math2
4  *  Copyright (c) 2003-2007 by Mattias Hultgren <tilda_o_tize@hotmail.com>
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; version 2 of the License.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public
17  *   License along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  */
20 
21 /*  See math2.cpp for news by version info  */
22 
23 
24 #ifndef MATH2_H_
25 #define MATH2_H_
26 
27 #include "vartypes.h"
28 #include "utf8_string.h"
29 #include "picture.h"
30 #include "vector.h"
31 #include "integer.h"
32 #include "real.h"
33 #include "complex.h"
34 #include "matrix.h"
35 #include <math.h>
36 
37 
38 #define MATH2_H_VERSION "v15"
39 #define MATH2_H_DATE    "2003-02 - 2006-10"
40 
41 namespace math
42 {
43 
44 
45 // this function must be called before any thing else is called
46 void init(void) throw(error_obj);
47 
48 
49 // this variable desides whether radians or degree should be used by sin, arg...
50 extern Complex degfix;
51 
52 /*  priority list
53 priority
54 number
55 
56  1     []    // Matrix brackets
57  2     ()
58  3     ""
59  4     methods such as set_pixel, get_type...
60  5     functions such as sin,cos,sqrt,ipart,time,++,--...
61  6     !
62  7     ^
63  8     * / \ mod
64  9     + -
65  10    == != < > <= >= ~=
66  11    and or xor not
67  12    =, +=, -=, *=, /=, \=, ^=
68 
69 */
70 
71 
72 class Variable;
73 class VariableList;
74 class CodeLine;
75 class Picture;
76 class CodeBlock;
77 class Array;
78 
79 
80 
81 typedef void *      void_ptr;     // these typedef's are used to do C++ style castings
82 typedef Complex *   Complex_ptr;
83 typedef Variable *  Variable_ptr;
84 typedef void (*BuiltinFunctionPtr)(Variable *res, Variable *left, const Variable *right, VariableList *private_varlist);
85 
86 void add_function(const utf8_string &name, BuiltinFunctionPtr newfunction,bool needleft,bool needright) throw(error_obj);
87 
88 // this function returns true if a file was autoloaded
89 bool autoload_file( const utf8_string &name ) throw(error_obj);
90 
91 // this is the directories that will be checked by autoload_file
92 extern Vector<utf8_string> autoload_directories;
93 
94 enum argument_types{ type_end,
95                      type_complex,  type_complex_default,
96                      type_floatx,   type_floatx_default,
97                      type_int64,    type_int64_default,
98                      type_integer,  type_integer_default,
99                      type_boolean,  type_boolean_default,
100                      type_picture,  type_picture_default,
101                      type_matrix,   type_matrix_default,
102                      type_string,   type_string_default,
103                      type_variable, type_variable_default,
104                      type_name,     type_name_default };
105 
106 void argument_check(const char *function, const Variable *input, ...) throw(error_obj);
107 
108 void colorrgb_to_colormatrix(const picture_h::colorrgb &color, Matrix *matr) throw(error_obj);
109 void colormatrix_to_colorrgb(const Matrix &matr, picture_h::colorrgb *color, uint32 index=1)
110                              throw(error_obj);
111 void colormatrix_to_colorrgbs(const Matrix &matr, Vector<picture_h::colorrgb> &colors)
112                               throw(error_obj);
113 
114 void color_list_get_color( const Vector<picture_h::colorrgb> &colors, floatx min, floatx max,
115                            floatx value, picture_h::colorrgb *out_color);
116 
117 // set this pointer to make the intern functions format numbers the way you want
118 extern Format *intern_format;
119 
120 extern VariableList global_varlist;
121 
122 
123 class Picture
124 {
125 private:
126 	floatx left,right,top,bottom;
127 
128 public:
129 	picture_h::picture pic;
130 
131 	picture_h::colorrgb bgcolor;
132 
133 	Picture() throw(error_obj);
134 	Picture(const Picture &src) throw(error_obj);
135 
136 	void operator=(const Picture &src) throw(error_obj);
137 
138 	bool operator==(const Picture &pict) const;
139 
140 	void set_size(int32 width,int32 height,floatx newleft,floatx newright,floatx newbottom,floatx newtop) throw(error_obj);
141 
142 	void set_window(floatx newleft,floatx newright,floatx newbottom,floatx newtop) throw(error_obj);
143 
clear(void)144 	inline void clear(void) { pic.clear(bgcolor); }
145 
146 	void line(floatx x1, floatx y1, floatx x2, floatx y2, bool antialiasing = false,
147 	          const picture_h::colorrgb &color = picture_h::color::BLACK);
148 
149 	void point(floatx x,floatx y,const picture_h::colorrgb &color = picture_h::color::BLACK);
150 
get_left(void)151 	inline floatx get_left(void) const { return left; }
get_right(void)152 	inline floatx get_right(void) const { return right; }
get_top(void)153 	inline floatx get_top(void) const { return top; }
get_bottom(void)154 	inline floatx get_bottom(void) const { return bottom; }
155 
156 	floatx get_x_value(int32 xpixel) const;
157 	floatx get_y_value(int32 ypixel) const;
158 
159 	int32 get_x_pixel(floatx xvalue) const;
160 	int32 get_y_pixel(floatx yvalue) const;
161 
162 	float get_float_x_pixel(floatx xvalue) const;
163 	float get_float_y_pixel(floatx yvalue) const;
164 
165 
166 	floatx get_unit_x_pixel(void) const;
167 	floatx get_unit_y_pixel(void) const;
168 };
169 
170 
171 
172 // Variable types
173 enum VariableType { VariableType_Complex, VariableType_Matrix,  VariableType_Array,
174                     VariableType_String,  VariableType_Picture,
175                     VariableType_Boolean, VariableType_Void };
176 
177 extern const char *VARIABLE_TYPE_NAMES[];
178 
179 
180 
181 void check_name_against_reserved(const utf8_string &name) throw(error_obj);
182 
183 class Variable
184 {
185 private:
186 	VariableType type;
187 
188 	union{
189 		struct{
190 			bool    boolean;
191 			char    *complex_buf[ sizeof( Complex ) ];
192 		};
193 		Matrix  *matr;
194 		struct{
195 			CodeLine   *code_line;
196 			utf8_string *str;
197 		};
198 		Array   *array;
199 		Picture *pic;
200 	};
201 
202 	utf8_string name;
203 
204 	void (*change_func)(Variable *ptr);
205 	void (*delete_func)(Variable *ptr);
206 
207 	bool inuse;
208 	bool isconstant;
209 	bool can_change_type;
210 
211 public:
212 
213 	Variable();
214 	Variable(const Variable &src) throw(error_obj);
215 	~Variable();
216 
217 	// if isconstant and can_change_type allows
218 	// this function copies the value/Matrix/function/string/list of the Variable
219 	// the name of the Variable will not be touched
220 	void operator=(const Variable &src) throw(error_obj);
221 
222 	bool operator==( const Variable &var ) const;
223 	inline bool operator!=( const Variable &var ) { return !(*this == var); }
224 
get_inuse(void)225 	inline bool get_inuse(void) const { return inuse; }
226 
227 	void set_void(void);
is_void(void)228 	inline bool is_void(void) const { return ( type == VariableType_Void ); }
229 
230 	void set_to_constant(void);
get_isconstant(void)231 	inline bool get_isconstant(void) const { return isconstant; }
232 
233 	void set_can_change_type(bool boolean) throw(error_obj);
get_can_change_type(void)234 	inline bool get_can_change_type(void) const { return can_change_type; }
235 
set_to_unused(void)236 	inline void set_to_unused(void) { inuse = false; }
237 
238 
239 	void set_name(const utf8_string &newname) throw(error_obj);
set_name_from(const Variable & src)240 	inline void set_name_from(const Variable &src) throw(error_obj) { set_name(src.name); }
241 	const utf8_string* get_name(void) const throw(error_obj);
242 
get_type(void)243 	VariableType get_type(void) const { return type; }
244 
has_name(void)245 	inline bool has_name(void) const { return (name.get_length() != 0); }
246 
247 	void signal_changed(void);
248 
249 	void clear(void) throw(error_obj);
250 
251 	void set_complex(const Complex &newvalue) throw(error_obj);
252 	const Complex* get_complex(void) const throw(error_obj);
253 	Complex* get_complex_rw(void) throw(error_obj);
254 
255 	void set_matrix(const Matrix *newmatrix) throw(error_obj);
256 	const Matrix* get_matrix(void) const throw(error_obj);
257 	Matrix* get_matrix_rw(void) throw(error_obj);
258 
259 
260 	void set_string(const utf8_string &newstring) throw(error_obj);
261 	void set_code_line(const char *new_code_line) throw(error_obj);
262 
263 	const utf8_string* get_string(void) const throw(error_obj);
264 	utf8_string* get_string_rw(void) throw(error_obj);
265 	// this will calculate the code_line's value/Matrix/list and return it
266 	void calc_code_line( Variable *res ) throw(error_obj);
267 
268 
269 	void set_array(const Array *newarray) throw(error_obj);
270 	const Array* get_array(void) const throw(error_obj);
271 	Array* get_array_rw(void) throw(error_obj);
272 
273 	void set_picture(const Picture *newpic) throw(error_obj);
274 	const Picture* get_picture(void) const throw(error_obj);
275 	Picture* get_picture_rw(void) throw(error_obj);
276 
277 	void set_boolean(bool newbool) throw(error_obj);
278 	bool get_boolean(void) const throw(error_obj);
279 
280 	// the change-event does only apply to Variable content not the name or flags like isconstant
set_change_func(void (* new_func)(Variable * ptr))281 	inline void set_change_func(void (*new_func)(Variable *ptr))
282 	              { change_func = new_func; }
283 
284 	// this function is called by the destructor
set_delete_func(void (* new_func)(Variable * ptr))285 	inline void set_delete_func(void (*new_func)(Variable *ptr))
286 	              { delete_func = new_func; }
287 
288 	void append_to_string( utf8_string &str, const Format &fmt, bool show_name=true ) const
289 	       throw(error_obj);
290 };
291 
292 class Array
293 {
294 private:
295 	uint32 nrofvariables;
296 
297 	Variable **array;
298 
299 	// this function increases the size with one, the new pointer is set to zero
300 	void increase_size(void) throw(error_obj);
301 
302 public:
303 	Array();
304 	Array(const Array &src) throw(error_obj);
305 	~Array();
306 
307 	void clear(void);
308 
309 	void set_size( uint32 new_size ) throw(error_obj);
310 
get_size(void)311 	inline uint32 get_size(void) const { return nrofvariables; }
312 
313 	const Variable * get_variable(uint32 nr) const throw(error_obj);
314 
315 	void set_variable( uint32 nr, const Variable &new_var) throw(error_obj);
316 
317 	// if var == 0 nothing will happen
318 	void add_variable(const Variable *var) throw(error_obj);
319 
320 	// after this call the Array owns the variable
321 	void add_this_variable( Variable *var ) throw(error_obj);
322 
323 	void insert( const Variable *var, uint32 at_pos ) throw(error_obj);
324 	void insert_this( Variable *var, uint32 at_pos ) throw(error_obj);
325 
326 	// if nr isn't existing nothing happens
327 	void remove_range( uint32 from_nr, uint32 this_many = 1 );
328 
329 	void operator=(const Array &src) throw(error_obj);
330 
331 	bool operator==(const Array &arr) const;
332 };
333 
334 
335 
336 
337 class VariableList
338 {
339 private:
340 	struct intern_variablelist
341 	{
342 		intern_variablelist *next;
343 
344 		uint32 idnr;
345 		uint32 isdeletable;
346 		Variable *var;
347 
348 		intern_variablelist();
349 		~intern_variablelist(); // deletes all 'intern_variablelist'-structs linked to *next
350 	}*varlist;
351 
352 public:
353 	VariableList();
354 	VariableList(const VariableList &src) throw(error_obj);
355 	~VariableList();
356 
357 	void operator=(const VariableList &src) throw(error_obj);
358 
359 	// returns the idnr for the variable thats called name (if there is more than one with that name the first found is returned)
360 	uint32 get_id(const char *name) const throw(error_obj);
361 
362 	bool check_for(const utf8_string &name) const;
363 
364 	// returns the highest idnr in the list
365 	uint32 get_highest_idnr(void) const;
366 
367 	// returns a pointer to the variable determind by idnr
368 	const Variable* get_pointer(uint32 idnr) const throw(error_obj);
369 	Variable* get_pointer_rw(uint32 idnr) throw(error_obj);
370 
371 	// creates a new Variable, a pointer to the created Variable is returned...
372 	Variable * create(const Variable &newvar, bool isconstant, bool isdeletable,
373 	                  bool can_change_type) throw(error_obj);
374 
375 	// adds a Variable note that the VariableList will be the owner of Variable newvar after this
376 	void add_this(Variable *newvar, bool isconstant, bool isdeletable, bool can_change_type) throw(error_obj);
377 
378 	void set_all_to_unused(void);
379 
380 	bool get_deletable(uint32 idnr) const throw(error_obj);
381 
382 	void make_undeletable(uint32 idnr) throw(error_obj);
383 
384 	// deletes a Variable, if it's deletable
385 	void remove(uint32 idnr) throw(error_obj);
386 
387 	// removes all Variables in the list, ignoring the isdeletable-flag
388 	void clear(void);
389 
is_empty(void)390 	bool is_empty(void) const { return (varlist) ? false : true; }
391 };
392 
393 
394 
395 
396 class CodeLine
397 {
398 private:
399 	class CodeLineNode
400 	{
401 	public:
402 		bool               soft_function;
403 		BuiltinFunctionPtr function;
404 		utf8_string        function_name;
405 		int32              tmpvariable_index; // this is the result variable
406 
407 		struct{
408 			int32       tmpvariable_index;
409 			bool        soft;
410 			Variable    *ptr;
411 			utf8_string name;
412 		}left, right;
413 
CodeLineNode()414 		CodeLineNode() { }
throw(error_obj)415 		CodeLineNode(const CodeLineNode &src) throw(error_obj)  {  *this = src;  }
~CodeLineNode()416 		~CodeLineNode() { }
throw(error_obj)417 		void operator=(const CodeLineNode &src) throw(error_obj)
418 		{
419 			try
420 			{
421 				soft_function = src.soft_function;
422 				function = src.function;
423 				function_name = src.function_name;
424 				tmpvariable_index = src.tmpvariable_index;
425 				left.tmpvariable_index = src.left.tmpvariable_index;
426 				left.soft = src.left.soft;
427 				left.ptr = src.left.ptr;
428 				left.name = src.left.name;
429 				right.tmpvariable_index = src.right.tmpvariable_index;
430 				right.soft = src.right.soft;
431 				right.ptr = src.right.ptr;
432 				right.name = src.right.name;
433 			}
434 			catch(...)  {  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
435 		}
436 
437 	};
438 	Vector<CodeLineNode> nodes;
439 	int32                nroftmpvariables;
440 	utf8_string          string;
441 	VariableList         autovarlist;
442 
443 	// this has a void* because I don't want to make struct Symbol visible in this header
444 	// the void* should be a Vector<Symbol>*
445 	void create_nodes(void *ptr, int start_at) throw(error_obj);
446 	void round_bracket_reducing(void *ptr, int start_at) throw(error_obj);
447 	void matrix_bracket_reducing(void *ptr) throw(error_obj);
448 
449 	void parse_pow_mods(void) throw(error_obj); // this is runned after create_nodes...
450 
451 	// this function returns the index of the tmp variable which is the matrix...
452 	int32 parse_matrix_creation( uint32 col, uint32 row ) throw(error_obj);
453 public:
454 	CodeLine();
455 	CodeLine(CodeLine &src) throw(error_obj);
456 	~CodeLine();
457 
458 	void operator=(CodeLine &src) throw(error_obj);
459 
460 	void set_code_line(const char * newstring, bool allow_variable_creation=true,
461 	                   VariableList *private_varlist=0) throw(error_obj);
462 
get_code_line(utf8_string * ret_string)463 	inline void get_code_line( utf8_string *ret_string ) const throw(error_obj) { *ret_string = string; }
464 
465 	// calculates the string that has been set by set_code_line/append_code_line
466 	void calc( Variable *answer, VariableList *private_varlist=0, Vector<Variable> *tmp_variables=0 ) throw(error_obj);
467 
get_nroftmpvariables(void)468 	inline int32 get_nroftmpvariables(void) const { return nroftmpvariables; }
469 
is_empty(void)470 	inline bool is_empty(void) const {  return (nodes.get_size() == 0);  }
471 };
472 
473 class CodeBlock
474 {
475 private:
476 	enum CodeBlock_Type { CodeBlock_Type_Void, CodeBlock_Type_Code, CodeBlock_Type_Start,
477 	                      CodeBlock_Type_Stop };
478 	enum CodeBlock_SubType { CodeBlock_SubType_None, CodeBlock_SubType_While,
479 	                         CodeBlock_SubType_If, CodeBlock_SubType_Else,
480 	                         CodeBlock_SubType_Return,
481 	                         CodeBlock_SubType_Break, CodeBlock_SubType_Continue };
482 	utf8_string filename;
483 
484 	class CodeBlockLine
485 	{
486 	public:
487 		int               line_number;
488 		CodeBlock_Type    type;
489 		CodeBlock_SubType sub_type;
490 
491 		union{
492 			CodeLine *code;
493 			int      pair_with;
494 		};
495 
496 		CodeBlockLine();
497 		CodeBlockLine(const CodeBlockLine &src) throw(error_obj);
498 		~CodeBlockLine();
499 		void operator=(const CodeBlockLine &src) throw(error_obj);
500 	};
501 
502 	Vector<CodeBlockLine> lines;
503 	uint32                inuse;
504 	VariableList          private_varlist;
505 	int32                 nroftmpvariables;
506 
507 	void add_void( CodeBlock_SubType sub_type ) throw(error_obj);
508 
509 	void add_line(const char *codeline, int linenr, bool allow_variable_creation,
510 	              CodeBlock_SubType sub_type = CodeBlock_SubType_None) throw(error_obj);
511 	void add_curley( CodeBlock_Type type, CodeBlock_SubType sub_type = CodeBlock_SubType_None,
512 	                 int pos = -1 ) throw(error_obj);
513 
514 	void set_code_intern(char *str, bool allow_variable_creation ) throw(error_obj);
515 	bool create_function(char *str, const utf8_string *only_allow_identifier) throw(error_obj);
516 
517 // only None, Break, Continue & Return are used
518 	void run_block( Vector<Variable> *tmp_variables, VariableList *this_private_varlist, CodeBlock_SubType &ret,
519 	                Variable *ans, int &start, bool expect_curley_ending = false ) const  throw(error_obj);
520 
521 	void pair_up_curleys(void);
522 	void add_automatic_curleys(void) throw(error_obj);
523 
524 public:
CodeBlock()525 	CodeBlock() { inuse = 0; nroftmpvariables = 0; }
526 	CodeBlock(const CodeBlock &src) throw(error_obj);
527 	~CodeBlock();
528 
get_inuse(void)529 	inline bool get_inuse(void) const { return (inuse != 0); }
530 
531 	void set_code(const char *newcode) throw(error_obj);
532 	void set_code_from_file( const utf8_string &new_filename,
533 	                         const utf8_string *only_allow_identifier = 0 ) throw(error_obj);
534 
535 	void calc( Variable *answer ) throw(error_obj);
536 
537 	void clear(void);
538 
539 	void operator=(const CodeBlock &src) throw(error_obj);
540 
541 	friend void wrapper_code_block_functions(Variable *res,Variable *left,const Variable *right,
542 	                                         const utf8_string &name) throw(error_obj);
543 	friend void wrapper_check_argument( int i, int i2, const Variable *right ) throw(error_obj);
544 };
545 
546 
547 } // namespace math
548 
549 #endif // MATH2_H_
550