Login [Register]
Don't have an account? Register now to chat, post, use our tools, and much more.
AHelper wrote:
Are you still interested in making the function parser? I will be getting onto the variable parser sometime...

I really need to get that new node created for functions and such... so little time
Oh yes, I definitely will be. I'll probably want to finish this academic paper and Chapter 12 first, though. Sad So little time is the name of the game these days.
So, I took the PC build of gCAS2 and modified it to use the new parser. So far so good. There are still bugs that cause crashes or bad generation, but I am quickly fixing them. I also added in a nice error reporter and turned debugging text off.

I will post images and such of it parsing.

Also, big problem is showing up. If I have (2+3*(4-5))/-2, gCAS2 is making it into 2+(3*(4-5))/-2) because the parser branches at the * and again at ). Trying to wrap my head around what is going wrong, but here is the debug output:
Code:
Welcome to gCAS2

>>(2+3*(4-5))/-2
===LOOP===
HOLD:
INCOM:
LAST:
First
parse_get_next_type '(2+3*(4-5))/-2
===LOOP===
HOLD:
INCOM:
LAST:
First
parse_get_next_type '2+3*(4-5))/-2
parse_number
parse_new_node
New number!
===LOOP===
HOLD: 2.000000
INCOM:
LAST: 2.000000
Hold set
parse_get_next_type '+3*(4-5))/-2
parse_op
parse_new_node
gcas_get_node_parse_type
===LOOP===
HOLD: 2.000000
INCOM: (2.000000+)
LAST: 2.000000
Hold set
parse_get_next_type '3*(4-5))/-2
parse_number
parse_new_node
===LOOP===
HOLD: (2.000000+3.000000)
INCOM:
LAST: 3.000000                                                                                                                                                                                                                               
Hold set                                                                                                                                                                                                                                     
parse_get_next_type '*(4-5))/-2                                                                                                                                                                                                             
parse_op                                                                                                                                                                                                                                     
parse_new_node                                                                                                                                                                                                                               
gcas_get_node_parse_type                                                                                                                                                                                                                     
===OP===                                                                                                                                                                                                                                     
HOLD: (2.000000+3.000000)                                                                                                                                                                                                                   
INCOM: (*)                                                                                                                                                                                                                                   
LAST: 3.000000                                                                                                                                                                                                                               
Branching                                                                                                                                                                                                                                   
===LOOP===                                                                                                                                                                                                                                   
HOLD:                                                                                                                                                                                                                                       
INCOM:                                                                                                                                                                                                                                       
LAST:                                                                                                                                                                                                                                       
First                                                                                                                                                                                                                                       
===LOOP===                                                                                                                                                                                                                                   
HOLD: 3.000000                                                                                                                                                                                                                               
INCOM: (3.000000*)                                                                                                                                                                                                                           
LAST: 3.000000
Hold set
parse_get_next_type '(4-5))/-2
===LOOP===
HOLD:
INCOM:
LAST:
First
parse_get_next_type '4-5))/-2
parse_number
parse_new_node
New number!
===LOOP===
HOLD: 4.000000
INCOM:
LAST: 4.000000
Hold set
parse_get_next_type '-5))/-2
parse_get_next_type '4-5))/-2
parse_op
parse_new_node
gcas_get_node_parse_type
===LOOP===
HOLD: 4.000000
INCOM: (4.000000-)
LAST: 4.000000
Hold set
parse_get_next_type '5))/-2
parse_number
parse_new_node
===LOOP===
HOLD: (4.000000-5.000000)
INCOM:
LAST: 5.000000
Hold set
parse_get_next_type '))/-2
The end
First return
===LOOP===
HOLD: (3.000000*(4.000000-5.000000))
INCOM:
LAST: (4.000000-5.000000)
Hold set
parse_get_next_type ')/-2
The end
Branch Returned
===LOOP===
HOLD: (2.000000+(3.000000*(4.000000-5.000000)))
INCOM:
LAST: (3.000000*(4.000000-5.000000))
Hold set
parse_get_next_type '/-2
parse_op
parse_new_node
gcas_get_node_parse_type
===OP===
HOLD: (2.000000+(3.000000*(4.000000-5.000000)))
INCOM: (/)
LAST: (3.000000*(4.000000-5.000000))
Branching
===LOOP===
HOLD:
INCOM:
LAST:
First
===LOOP===
HOLD: (3.000000*(4.000000-5.000000))
INCOM: ((3.000000*(4.000000-5.000000))/)
LAST: (3.000000*(4.000000-5.000000))
Hold set
parse_get_next_type '-2
parse_get_next_type '/-2
parse_number
parse_new_node
===LOOP===
HOLD: ((3.000000*(4.000000-5.000000))/-2.000000)
INCOM:
LAST: -2.000000
Hold set
parse_get_next_type '
End string
The end
Branch Returned
===LOOP===
HOLD: (2.000000+((3.000000*(4.000000-5.000000))/-2.000000))
INCOM:
LAST: ((3.000000*(4.000000-5.000000))/-2.000000)
Hold set
parse_get_next_type '
End string
The end
First return
D: (2.000000+((3.000000*(4.000000-5.000000))/-2.000000))
>1.966667
>>

Yeah, I am probably not going to be the only one having issues understanding that Razz

<edit>

Fixed this issue. So, now that gCAS2 is working nicely, can anyone post in this thread complex math expressions? Note, only use +-*/^(), no variables or functions. I am making my own test functions. For ex, the last one that fixed loads of issues was (2+3*(4-5))/-2. Also, giving me ones with errors in them are also wanted as the error checking is still being tweeked.

<edit>

Here is an example of error checking:

Code:
Welcome to gCAS2

>>2+(3-4))
Error code 6
Reason: An extra right parenthesis was found.
2+(3-4))
       ^
>>
Variable support is being added. So, design issue time. Right now, you must type in 2*x for a variable, not 2x. The later can bring in issues...

(Will finish this posfs)
Commit 67 added variable support into gCAS2. The PC build has x and y defined as pi and -9.8, respectively. You cannot define variables yet, this will be added shortly.

Also, I was thinking about function support in gCAS2. I will need to make the cas use operation flags to determine how and when things should be evaluated. For example, right now, if you do (x+1)*(x+2)*(x+3), gCAS2 will expand everything in that function, making loads of nodes. This isn't OK for stuff like (x+1)^100, clearly. A flag will be used to only expand/foil/distribute (or otherwise add more nodes) at certain times. Other flags would be used for things like approx, degrees (radians default), factoring, and making variable-sized nodes.

Side-question, anyone know any cas theory for 2-sided expressions? It would be awesome for gCAS2 to solve stuff like solve(y=e^(2*x),x). I am looking myself, but don't know much on where to start looking other than aimlessly googling...

Edit: I am thinking about making certain numbers constant, like e, π, and infinity. Instead of making them decimal numbers right away, it will keep it in forms like e^π. Trying to figure out how to get it to work. I could treat it like a variable... trig functions would handle them nicely and such, but I don't know how it would work elsewhere.

Edit: So, I am trying to think about how to order things in the CAS's evaluate function. I have this order:
  1. Evaluate simple algorithms that do basic algebra.
  2. Distribute multiplication/division (if flagged)
  3. Group similar nodes into a vs node (cas_node_vs, variable sized).
  4. Approximate constants and fractions (if flagged)
also trying to get cas_node_vs put into the code, as well as flags... This will be ugly

Edit: gCAS2 is now breaking all compat. except for variables (somehow). Get ready to rewrite gCAS2 interaction code when these upgrades are done.
After hours of bashing my face into my code, I finally added in support for:
  1. cas_node_vs is handled by the evaluator. Each child node gets evaluated.
  2. The evaluator works in levels in order to force an order of when certain algorithms are used.
  3. Added in rough (holy hell) gcas_alg_group_* functions that will detect multiple levels of addition/subtraction and make a variable-sized node. The group can be sorted if the base and powers match. No advanced matching. 2a can be matched as it is a nNUMBER, but not 2*a*b as it is a nMULT node.
  4. The parser has a bug where negative variables, like -x+1, will crash as the parser expects a number after a negative, not a variable.
  5. No memory leaks
  6. Functions can safely use the cas_node_vs so long that the node itself isn't passed to the evaluator, as it will try to sort it, causing nodes to be moved around and such.
  7. cas_node_vs currently does get smaller when you sort it, but it doesn't remalloc to save space.
  8. Distributing to one of these things will work like magic.
That's my comments on this so far. Also, you can see the evaluator working its magic here:
Code:
[Joshua@Joshua gCAS2]$ valgrind --tool=memcheck ./gcas2
==11376== Memcheck, a memory error detector
==11376== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==11376== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==11376== Command: ./gcas2
==11376==
Welcome to gCAS2

>>(2*a+3)*(a+9)                     
((2.000000a+3.000000)*(a+9.000000))
(((2.000000a+3.000000)*a)+((2.000000a+3.000000)*9.000000))
(((2.000000a*a)+(3.000000*a))+((2.000000a+3.000000)*9.000000))
((2.000000a^2+(3.000000*a))+((2.000000a+3.000000)*9.000000))
((2.000000a^2+3.000000a)+((2.000000a+3.000000)*9.000000))
((2.000000a^2+3.000000a)+((2.000000a*9.000000)+(3.000000*9.000000)))
((2.000000a^2+3.000000a)+(18.000000a+(3.000000*9.000000)))
((2.000000a^2+3.000000a)+(18.000000a+27.000000))
(2.000000a^2+3.000000a+18.000000a+27.000000)    // Here is where the grouping was done
(2.000000a^2+(3.000000a+18.000000a)+27.000000)  // Notice the lack of () around numbers in a group
(2.000000a^2+21.000000a+27.000000)
>(2.000000a^2+21.000000a+27.000000)
==11376==
==11376== HEAP SUMMARY:
==11376==     in use at exit: 0 bytes in 0 blocks
==11376==   total heap usage: 100 allocs, 100 frees, 1,444 bytes allocated
==11376==
==11376== All heap blocks were freed -- no leaks are possible
==11376==
==11376== For counts of detected and suppressed errors, rerun with: -v
==11376== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 8)


EDIT!!!

Functions are now supported!!! A new node type, nVS_FUNCTION, was added for parameters passed to functions. I have placeholder code everywhere right now, but functions fit into the node tree. For example, 2*sqrt(6*2,2) gives me 2*sqrt(12,2). I don't have any function algorithms, but I have code to support function parsing, evaluation of parameters, and printing. WOO!!

Edit. How functions work...

Functions are special-case cas_nodes that contain info on which function they are and the parameters. Firstly, functions are regular cas_node variables with the type as nFUNCTION. The nB is used to tell what function it is, like fSQRT. n1 is a pointer to a cas_node_vs of type nVS_FUNCION. n2 is unused. There is a structure, function_names, that connects f___ ids to their textual names.

I am working on square root calculation with and without approximation. I would need a factoring function to help special things along, but normal numbers should be simplified.
So, about functions (aimed at KermM). Functions contain 2 nodes, the function cas_node and the parameter-filled cas_node_vs. (Look at the latest gcas2.h for cas_node_vs).

Function nodes are made this way: Make a blank node, set node->number.nB to the function number (fSQRT, fARCSIN, etc.). Make a cas_node_vs with each parameter being a node in its array. Store that to node->n1 (function node).

Function alg. functions are declaired as unsigned char gcas_alg_func_xxx(cas_node *node, cas_eval_level flags). The node is the function node. Now, please note that this will change! The intended declairation will be unsigned char gcas_alg_func_xxx(cas_node **node, cas_eval_level flags) for the purpose of partially evaluating a function, ex) sqrt(Cool -> 2*sqrt(2).

The parser doesn't know how many parameters your function will need in every case, so it leaves it up to the function alg. to check. I still don't have a method of reporting errors yet, but it will be something along the lines of making an error node.

If anyone wants to make functions, have at it!

Opinion time! If I have this
Code:
>> 1+x
> 1+x
>> x:=4
>>y:=1+x
Would you expect y to contain 1+x, or the result of 1+x? Example with the former:
Code:
>> y
> 5
>> x:=5
>> y
> 5
---- Latter would return 6 instead.

If I do the latter, then I can impove ease of use, but the parse would get a bit messed up. Also, you cannot delete the x variable since it will be referenced in the y variable. Example of ti89 piping/substitution -> gCAS2 parametric varaibles

Code:
::TI89::
1+x
        x+1
1+x->y
        x+1
y|x=2
          3
1->x
          1
1+x->y
          2
::gCAS2::
// The above will do the same thing in the current state, below will be the proposed change
>> 1+x
> 1+x
>> y:=1+x
>> y
> 1+x
>> y[x=3]
>4
>> x:=5
>> y:=2*x
>> y
> 10
>> y[x=0.5]
> 1
>> varaiblesarefun:=3.1415
>> y[x=variablesarefun]
> 6.283

Downside: The parser would need to explode since local variable substitutions would get insane in the code.
Upside: You can see what the variables are, so that's good

Code:
>> list
x:=5
y:=1+x
variablesarefun:=3.1415
>>


Just wanting to see if anyone wants a new design or if the AMS method is good enough.
So, while I am still adding in initial function support (test function being sqrt), I would like to gather up methods of differentiation and solving indefinate integrals. These would be very helpful for calculus expressions and for boosting graphing capabilities. Without enough rules in the cas, the functionality will suffer by it not being able to solve stuff.

So, derivates. I know of standard rules, like product/division/chain rules, but I am looking for other methods.

Integrals, I know of integration by parts, substitution (idk how a cas would figure out what to pick :-S), and other known integrals.

I could spend loads of time on google, but it would take a while for me to understand them well enough for use, plus I will be focusing less on the actual cas...

<edit>

Just throwing this out there, I finished gcas_alg_func_sqrt yesterday. It works as expected.
Code:
>> sqrt(8)
> 2*sqrt(2)
>> sqrt(123*123)
> 123

I will be adding in simplifying, starting with modifying gcas_alg_multdiv and adding in gcas_get_gcd/gcas_get_cd to help with simplifying. Right now, gCAS2 would take (2*2)/4 and return 4/4 normally. (fApprox set as a flag would give you decimal answers everywhere, not the same)
So, while I was learning about python, I stumbled across its usage of a reference counter. I will probably add that to the variables in gCAS2 since right now there is now way to nicely delete variables and such.
AHelper wrote:
So, while I was learning about python, I stumbled across its usage of a reference counter. I will probably add that to the variables in gCAS2 since right now there is now way to nicely delete variables and such.
Nifty! I must say that I've forgotten once again what, once I clear away a few things on my to-do list, I need to do to get gCAS and Graph3DP up to speed. Still the function support?
Yup, functions need help. Also, there is a bug somewhere in the parser. I don't remember what caused it, but has to do with left parenthesis and branching.

I need to make sure that the gcas2.c in subversion is up to date....
A warm welcome from subversion.


Code:
[tiny@Tiny glassos-svn]$ svn commit -m "Pushing all changes to svn so I don't lose them"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/tiny/projects/glassos-svn/trunk/src/libs/gui/gui.c' remains in conflict
[tiny@Tiny glassos-svn]$ svn resolved gui.c
[tiny@Tiny glassos-svn]$ svn commit -m "Pushing all changes to svn so I don't lose them"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/tiny/projects/glassos-svn/trunk/src/libs/gui/gui.c' remains in conflict
[tiny@Tiny glassos-svn]$ svn resolved trunk/src/libs/gui/gui.c
Resolved conflicted state of 'trunk/src/libs/gui/gui.c'
[tiny@Tiny glassos-svn]$ svn commit -m "Pushing all changes to svn so I don't lose them"
^Csvn: Commit failed (details follow):                <<< Freezes
svn: At least one property change failed; repository is unchanged
svn: Caught signal
[tiny@Tiny glassos-svn]$ ^C
[tiny@Tiny glassos-svn]$ svn commit -m "Pushing all changes to svn so I don't lose them"
Sending        trunk/Makefile
svn: Commit failed (details follow):
svn: File or directory 'Makefile' is out of date; try updating
svn: resource out of date; try updating
[tiny@Tiny glassos-svn]$ svn update
Conflict discovered in 'trunk/src/gCAS2/gcas2.c'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: ^C^Csvn: Caught signal



Didn't I just resolve conflicts?


Code:
[tiny@Tiny glassos-svn]$ svn update
Conflict discovered in 'trunk/Makefile'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: tc
G    trunk/Makefile
Conflict discovered in 'trunk/src/kernel/page1C.h'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: ^C^Csvn: Caught signal
[tiny@Tiny glassos-svn]$ cd trunk/src/kernel/
[tiny@Tiny kernel]$ svn remove page1C.h
svn: Use --force to override this restriction
svn: 'page1C.h' has local modifications
[tiny@Tiny kernel]$ svn remove page1C.h --force
D         page1C.h
[tiny@Tiny kernel]$ make
<snip>
[tiny@Tiny kernel]$ cd ../../..
[tiny@Tiny glassos-svn]$ svn commit -m "Pushing all changes to svn so I don't lose them"
Sending        trunk/src/Makefile
svn: Commit failed (details follow):
svn: File or directory 'Makefile' is out of date; try updating
svn: resource out of date; try updating
[tiny@Tiny glassos-svn]$ svn update
   C trunk/src/kernel/page1C.h
Conflict discovered in 'trunk/src/kernel/page1C.h'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options:



Where's that git...

==================

Adding your own functions to gCAS2's source - Not using the custom function API (to be added)

gCAS2 knows the difference between multiplication and functions only because it doesn't allow implied multiplication. Right now, a function consists of the first character being a letter and ending in a '('. a123() is a valid function name.

gCAS2 has a constant lookup table consisting of the function name, ID number, and handler pointer. If you want to make a function, you need a handler. The syntax for one is

Code:
unsigned char gcas_alg_func_{FUNCTION NAME HERE}(cas_node **n, cas_eval_level flags)

This function will be called every time your function is seen. It may get called multiple times due to the way that it parses nodes and handles flags.

You should be familiar with gcas_node structs before writing your function. (I don't have documentation for it, just post in this thread).

The **n is a pointer to your node pointer. This is done so that you can modify your function. Lets take sqrt(Cool for example. In order to simplify it to 2*sqrt(2), you must change the root node (currently your function) to a multiplication node.

The flags parameter just says what your function should do when it is called. Please use this all of the time. You can see the different values in gcas2.h under cas_eval_level.

Lastly, the return value is a boolean value. Return true if you modified the tree, and false if nothing happened. (I need to check on this, but I think you only need to return true if you modify the root node, aka. gcas_node **n.)

Now that you have a function handler, now you must inject your function name into gCAS2. This tutorial only shows you how to statically include it in gcas2.c. Inside of gcas2.h, locate:

Code:
typedef enum
{
  fSQRT,
  fSIN,
  fCOS,
  fTAN,
  fACOS,
  fASIN,
  fATAN,
  fPRINT // testing
} cas_function_types;

This struct holds the function IDs and are used in the function nodes and the function names when parsing. Add in your function to the list using the same format as the other entries. The name should be the same text used in the name of the function handler.

Next, find the struct at the bottom of the gcas2.h file named 'function_names'. Above it will be a list of function definitions. Add in a definition of your function here. Next, add an entry to the 'function_names' struct so that gCAS2's parser can identify your function and process it. The format is {ID (cas_function_types), name (char*), handler (your function's name)}.

When you are done with that, compile gcas2.c and try running your function!

(Note: to build gCAS2, you can use the makefile provided and make a binary using `make linux`. Uses g++)
Quote:
Right now, a function consists of the first character being a letter and ending in a '('
Does that make "a-5+4(" a valid function name? Or is there an additional constraint that all characters between the initial letter and the "(" must be alphanumeric? Anyway, moving past the nitpicking, this all makes sense to me and seems quite straightforward. I see that the enum already have the trig functions in it, but does that mean that they're implemented from my implementations?
Let me check. I feel like I was lieing when I said it took alphanumeric and not just alpha- function names.

No, I just put placeholder enums. The functions have to be created according to the steps above.

Getting back to you on that function name, I was wrong. Only alpha characters can make up the function name. If you want, that can be changed to only accept alphanumeric characters.
For now alpha characters are fine. The only thing I'm thinking of is if we eventually want to have functions like log10, log2, and related.
log(10,x)

Smile
AHelper wrote:
log(10,x)

Smile
I guess, but surely there might eventually be some functions that need to have numbers in them? I vote we not worry about it for now, though. I'll grab your current source and see what I need to do as far as merging it with my existing Graph3DP code. How much has changed about the tree/parse/assemble mechanism?
Look at the main function. I haven't worked on gcas2 in weeks, so I forgot exactly what needs to be changed in graph3dp. The parsing calls, probably. Oh, and whatever functions you use to display stuff with need to handle functions and variable-sized nodes. You can look at the debug_print* functions for that.
I just built gCAS2 for GlassOS and what do ya know? Works perfectly. sqrt(4) gives 2 and other math stuff work with it.

Now then, about function size... For hardware like PCs and the Prizm, code size isn't that much of a concern. For the TI84+(SE), it is a problem as the library right now must fit into 16KB, and it does.. barely. So, I will be converting large functions, only algorithms, into z80 asm in order to not have 2.6KB functions. This doesn't change how other platforms use the library, however if I cannot get the size down (which will happen eventually), then the library will split up into multiple source files. For GlassOS, each source file will be its own library. For other platforms, you will not have to care other than to compile and link all of the files.

Quick question: Is there a way to tell if a float (IEEE 754) is a whole number?
Let me jot this down before I forget: If bit 30 is 1, then bits 23-29 say how many bits the fraction can be while still being whole. It works, trust me.

Also: Woo! I added in a z80 asm version of gcas_alg_addsub. SDCC's is 703 bytes and mine is 309, saving 394 bytes! And that's without optimizing my own function! I plan to do that same to the multdiv function, a giant 3KB function. Don't worry, C functions will be made first and will stay so you can use it on other platforms Smile
I preliminarily integrated the new gCAS2 into Graph3DP, without bothering to fill in any of the new functions yet. Relatively predictable results, plus a few that I wasn't quite expecting:

:: .1*X*Y crashes, but 0.1*X*Y does not
:: In the source, gcas_alg_func_integ() just sort of stops in the middle. /me scowls at AHelper for checking in unbuildable code, then remembers that AHelper is his hero for sharing gCAS2 at all.
:: Trying to parse anything with sin/cos/tan in it crashes (of course, since I didn't fill in the functions yet)
:: I had to port over a lot of my changes from the original gCAS2 for it to compile for the Prizm.
:: One of the particularly important ones was changing gcas_tree_copy to return an int, so that it can indicate a failure in malloc and recursively die gracefully if it fails.
:: I was disappointed to note that invalid entries like 3+-2 or 3.3.3 did not seem to trigger a parser error via parse_is_error().
*bump* I've been fixing a bunch of odd issues in gCAS2, like one case pFUNCTION: line that seemed to be randomly missing and some hard-coded magic numbers. I'm still trying to narrow down why all functions crash. Also, does the gcas_parse() function free the tree if it encounters an error? I ask before freeTree() crashes on a tree that was created from an equation with an error in it.

Edit: I wrote a new gcas_size_tree() that I believe should be functionally correct. Here it is if anyone else needs it:

Code:
int gcas_size_tree(cas_node* tree) {
    printf("%02d recursing %p -> [ %p %p ]\n",tree->type,tree,tree->n1,tree->n2);
   if (tree->type == nVS_FUNCTION || tree->type == nVS_ADD || tree->type == nVS_SUB) {
      int size=1;
      for(int i=0; i < (int)(((cas_node_vs*)tree)->size); i++) {
         size += gcas_size_tree(&(((cas_node_vs*)tree)->nodes[i]));
      }
      return size;
   } else {
      return 1+
            ((tree->n1 != NULL)?gcas_size_tree(tree->n1):0)+
            ((tree->n2 != NULL)?gcas_size_tree(tree->n2):0);
   }
}
However, I see that gcas_tree_copy() will need similar changes; I am putting that together now.

Edit #2: I believe that cas_node_vs is flawed in that its nodes member is of type cas_node* rather that cas_node**. I believe this means that it has a direct array of cas_nodes, and thus none of its children can be of type cas_node_vs. Regardless, here's my gcas_tree_copy() that follows your framework as it is:

Code:
int gcas_tree_copy(cas_node* dest, cas_node *src) {

   if (src->type == nVS_FUNCTION || src->type == nVS_ADD || src->type == nVS_SUB) {
      if (NULL == (dest = realloc(dest,sizeof(cas_node_vs))))
         return -1;
      memmove(dest,src,sizeof(cas_node_vs));
   
      int size = (int)(((cas_node_vs*)src)->size);
      if (NULL == (((cas_node_vs*)dest)->nodes = malloc(size*sizeof(cas_node))))
         return -1;
      memmove(((cas_node_vs*)dest)->nodes,((cas_node_vs*)src)->nodes,size*sizeof(cas_node));
   } else {
      memmove(dest,src,sizeof(cas_node));
      if (src->n1)
      {
         if (NULL == (dest->n1 = (cas_node*)malloc(sizeof(cas_node))))
            return -1;
         if (0 > gcas_tree_copy(dest->n1, src->n1))
            return -1;
      }
      if (src->n2)
      {
         if (NULL == (dest->n2 = (cas_node*)malloc(sizeof(cas_node))))
            return -1;
         if (0 > gcas_tree_copy(dest->n2, src->n2))
            return -1;
      }
   }
   return 0;
}


Edit #3: The more of your code I read, the more confused I am about what the nodes member of a cas_node_vs is actually supposed to be. You do this super-awkward casting every time you use it that makes it look as if you actually did mean it to be a cas_node*[], even though it's not; is that what you meant? If so, I will do my best to overhaul my copy to have that.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 9 of 12
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement