Post Reply 
HP Prime CAS programming
02-19-2015, 08:21 PM (This post was last modified: 03-02-2015 04:27 PM by Han.)
Post: #1
HP Prime CAS programming
There are several methods to make use of CAS commands in a program on the HP Prime.

1. CAS("command(arg1,arg2,...,argn)")
2. CAS.command("arg1","arg2",...,"argn") or CAS.command("arg1,arg2,...,argn")
3. Create an actual CAS function via #cas and #end

Recall that an HP Prime Programming Language (HPPPL) program is essentially a collection of commands that are executed in the Home view. And in the Home view, most CAS commands must be treated with care. Techniques 1 and 2 behave mostly the same, and are generally used within HPPPL programs to gain access to CAS commands. Technique 3 is equivalent to creating a function in the CAS view, but the function remains resident in storage even after the use of the 'restart' command. This needs further clarification: the program's source remains in storage, however the command must be "re-compiled" in order to reuse it. Thus, technique 3 is more akin to creating a macro file that needs to be run (i.e. "compiled") after each instance of the 'restart' command. This is the advantage of creating an HPPPL program that uses techniques 1 and 2 since HPPPL programs are always resident in memory after compilation (there is no 'restart' equivalent for Home view).

Example of Technique 1

Suppose we wish to create a program that takes a formula for the function \( f(x) \) and determine the values of \( x \) such that \( f'(x) = 0 \). For our example, let \( f(x) = x^3-3x \). If we do this by hand in the CAS view, we would likely type in:

Code:
f:=x^3-3*x;
derf:=diff(f,x);
solve(derf,x);

and obtain the list: { -1, 1 }. We could simplify these steps into:

solve(diff(f,x),x);

This simplification allows us to create the following program:

Code:
EXPORT CASCMD1(f)
BEGIN
  local cmd:="solve(diff(" + f + ",x),x)";
  CAS(cmd);
END;

To actually use the program, we must type: CASCMD1("x^3-3*x"). Notice that the argument f is actually a string representing the expression \( x^3-3x \). Some important points:
  • We CANNOT use CAS("solve(diff" + f + ",x),x)") in place of CAS(cmd). That is, the argument of CAS() must either be a string or a variable whose content is a string, and the string must be a valid CAS input. The argument of the CAS() command must not be an expression, since the CAS() command will then simply evaluate the expression in the CAS view -- i.e. it will simply add the three strings using the CAS view rules.
  • It is possible to save the results using, say, L1:=CAS(cmd); to save the results into the built-in list L1. More generally, one may store the result into any variable whether local or global or built-in.
  • Sometimes the "type" of the result may be altered due to differences in how the CAS and Home views represent that type. For example, one may create a symbolic matrix for the input variable f (in the form of a string) and the result is converted into a list of lists. Accessing the entries is still the same, but any type checks will require extra care.
  • If we have result:=CAS(cmd); then we can (generally) use 'result' without having to convert it into a string.
  • We can create a CAS variable via: CAS("casvar:=0"); -- of course, change 'casvar' accordingly.

Example of Technique 2

Again, under the same premise as in the previous example, we can create the following code:

Code:
EXPORT CASCMD2(f)
  local result:=CAS.diff(f,"x");
  result:=CAS.solve(result,"x");
END;

We can use 'result' directly with the solve() command. If, however, we had wanted to solve the equation \( f'(x) = -3 \), or equivalently \( f'(x) + 3 = 0 \) then it is NOT simply a matter of changing the last line of code to: result:=CAS.solve(result+3,"x"); because the expression result+3 is computed as if we were in the Home view. And in the Home view, the content of 'result' -- which is the expression '3*x^2-3' -- must be resolvable. If the variable 'x' does not exist, then an error occurs. So the following modification is required:

Code:
// modification so that we solve f'(x)=-3
EXPORT CASCMD2(f)
  local result:=CAS.diff(f,"x");
  result:=STRING(result) + "+3"; // or simply result:=STRING(result) + 3; since HPPPL can auto-convert where there is no ambiguity
  result:=CAS.solve(result,"x");
END;

Example of Technique 3

The simplest (in terms of coding and legibility of code) is by creating a CAS function. The easiest way to create a CAS program is to simply "solve" our problem in the CAS view. Then, open the program editor and create a new CAS program. Finally, simply copy and paste (from the CAS view) the relevant commands used in the previous session.

Code:
#cas
CASCMD3(f):=
BEGIN
  derf:=diff(f,x);
  solve(derf,x);
END;
#end

Some important notes:
  • This program will create a CAS variable named derf. If we want derf to be only temporary, then we can create a local variable named derf.
  • Local variables must necessarily be declared first (it seems). Otherwise a syntax error occurs. Moreover, we cannot combine a declaration with an assignment as in non-CAS programs. So local derf:=<blah> would not be allowed. Below is an example of the use of a local CAS variable.
    Code:
    #cas
    CASCMD3(f):=
    BEGIN
      local derf;
      derf:=diff(f,x);
      solve(derf,x);
    END;
    #end
  • In the CAS view, the input to our program can be typed without the " symbol. In the Home view, our program (being a CAS command) requires that the input be quoted with the " symbol.

The Hybrid Approach

It is also possible to create a hybrid project. That is, a single source file could potentially have both non-CAS programs _and_ CAS programs. For example:

Code:
EXPORT NONCAS(f)
BEGIN
  CAS.diff(f,"x");
END;

#cas
CASPROG(f):=
BEGIN
  local result;
  result:=NONCAS(f);
  solve(result,x);
END;
#end

CASPROG("x^3-3*x") from the Home view will return { -1, 1 }.

Pros and Cons

There are benefits as well as drawbacks to using each technique. As of firmware 6975:
  • Local variables in CAS programs MUST be declared at the beginning of each procedure. Moreover, the declarations must be separate from initialization. So whereas local foo:=bar; is completely fine for non-CAS programs, this single line must be split into local foo; foo:=bar; for CAS programs.
  • CAS programs may be programmed to have dynamic input. For example,
    Code:
    #cas
    myprog(args):=
    BEGIN
      local s:=SIZE(args);
      CASE
        IF s==0 THEN
          // code for when no arguments supplied
        END;
        IF s==1 THEN
          // code for when a single argument is supplied
        END;
      END;
    END;
    #end
    may be called with myprog(), myprog(arg1), myprog(arg1,arg2), ... etc. Note that a more complete check would also include the TYPE() of the variable s (since using SIZE() on matrices will return the result: [ row column ]). The program must, of course, properly handle the various combinations of inputs. In order to achieve an equivalent program in HPPPL, we could implement something like:
    Code:
    EXPORT myprogram(arg)
    BEGIN
      local s:=SIZE(arg);
      CASE
        IF s==1 THEN
          // we have a non-list argument; perhaps dispatch based on type of argument
        END;
        IF s>1 THEN
          // we have a list; dispatch based on size of list
          CASE
            IF s==2 THEN
              // blah
            END;
            IF s==3 THEN
              // blah
            END;
          END; // inner case
       END; // if s>1
      END; // outer case
        
    END;
    This program would be called with myprog(arg1) OR myprog({arg1}), myprog({arg1,arg2}), myprog({arg1,arg2,arg3}), etc. Unfortunately there does not seem to be a way to accept the hybrid case: both no argument or variable number of arguments.
  • Non-CAS programs currently have a more usable (though still broken) debugger.
  • Non-CAS programs do not have to be "recompiled"; CAS programs must be "recompiled" should one use the restart command in CAS view.
  • Pure CAS programs do not have to deal with type conversion between CAS and non-CAS programs.
  • Non-CAS programs that use CAS commands will generally have to involve string manipulation.
  • Non-CAS programs can make use of "interface" commands such as CHOOSE() and INPUT() whereas CAS programs are generally not interactive. A workaround is to use the EXPR() command to call these commands indirectly. EXPR() works like CAS() in that both take input strings.
  • Both non-CAS and CAS programs must carefully account for the fact that some commands are case sensitive. Generally speaking, upper-case commands are Home-view commands whereas lower-case commands are CAS-view commands. In HPPPL, most of the time, there is no distinction between cases. That is, the command TYPE() and type() are no different. However, CAS-only commands must be typed in lower-case (e.g. mat2list() is a CAS command that works in Home view, but only if typed as mat2list() and not MAT2LIST() -- the latter does not exist). CAS programs, however, DO distinguish between TYPE() and type().
  • All variables not declared as local are considered global CAS variables and persist even after the program finishes. Thus, programmers may possibly have to use purge() to clean up any mess their programs leave.
  • The equality == behaves differently in CAS vs non-CAS. For example: in the CAS view, testing equality between a list and a real value returns a 0 (due to type checking, perhaps?) whereas in the Home view testing equality between a list and a real value applies the test to the entire list, resulting in a list of 0's and 1's.
  • I'm sure there are more....

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-19-2015, 08:41 PM (This post was last modified: 02-20-2015 10:40 AM by salvomic.)
Post: #2
RE: HP Prime CAS programming
Thank you, Han,
I'm bookmarking this guide, very interesting for me.

Please, explain also something about how pass arguments, i.e how pass an optional argument...

Have a nice day!

***
EDIT:
please, Han, advise, if possible, how to make a Help for a customized program.
I would like to help about the list of parameters when the program start (or pressing Help key, but I don't know if it's possible)...

∫aL√0mic (IT9CLU), HP Prime 50g 41CX 71b 42s 12C 15C - DM42 WP34s :: Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
02-19-2015, 10:35 PM (This post was last modified: 02-19-2015 10:44 PM by dg1969.)
Post: #3
RE: HP Prime CAS programming
Thank you very much Han, for theses explanations. I am very interested in this Chapter. I will follow assiduously this post.

In my mind local variables were prohibited in the CAS side... And for me instructions inside #CAS #end (in a non cas program) were carried out only once during compilation (a kind of script)... Can we place several blocks #cas #end in a source file ?
Find all posts by this user
Quote this message in a reply
02-20-2015, 01:22 PM
Post: #4
RE: HP Prime CAS programming
(02-19-2015 08:21 PM)Han Wrote:  There are several methods to make use of CAS commands in a program on the HP Prime...

...When I have time, I'll add more to this. There is still a lot more to discuss (e.g. the scope of CAS variables inside a HPPPL program and vice versa), but this should allow many folks to get started with CAS programming.

This is excellent Han, even after all this time, your article has cleared up many details and annoyances with CAS, at least for me. Thanks very much!

Suggestion: Move this post to the "Articles" Forum, intended for reference works like this.

Moderator suggestion: Possible addition of a new "Prime Articles" forum. The Prime is so vast and new, and complex to learn, that a dedicated place for articles such as this would be tremendously helpful to folks new to the Prime and/or the forum, where they can pick from a small, focused set of instructional articles. While there is a wealth of info stuffed into the current Prime forum now, a reader must wade through hundreds of threads with thousands of messages to find the dozen or so seminal articles that explain and illustrate with examples many of the most confusing and/or complex issues learning Prime.

--Bob Prosperi
Find all posts by this user
Quote this message in a reply
02-21-2015, 03:21 AM (This post was last modified: 02-21-2015 03:21 AM by Han.)
Post: #5
RE: HP Prime CAS programming
(02-20-2015 01:22 PM)rprosperi Wrote:  Suggestion: Move this post to the "Articles" Forum, intended for reference works like this.

Eventually, it will be moved. I find it more helpful to write about topics that are more important to users and prefer to this forum for the simple fact that it allows replies and keeps the discussion to a single thread. So for now (since it's nowhere finished), I thought I'd post here so that people can post replies/suggestions/criticisms/etc since that sort of discussion is not allowed in the articles forum.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-21-2015, 06:21 AM
Post: #6
RE: HP Prime CAS programming
(02-21-2015 03:21 AM)Han Wrote:  So for now (since it's nowhere finished), I thought I'd post here so that people can post replies/suggestions/criticisms/etc since that sort of discussion is not allowed in the articles forum.

I agree!
TU

∫aL√0mic (IT9CLU), HP Prime 50g 41CX 71b 42s 12C 15C - DM42 WP34s :: Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
02-21-2015, 01:54 PM
Post: #7
RE: HP Prime CAS programming
(02-21-2015 03:21 AM)Han Wrote:  
(02-20-2015 01:22 PM)rprosperi Wrote:  Suggestion: Move this post to the "Articles" Forum, intended for reference works like this.

Eventually, it will be moved. I find it more helpful to write about topics that are more important to users and prefer to this forum for the simple fact that it allows replies and keeps the discussion to a single thread. So for now (since it's nowhere finished), I thought I'd post here so that people can post replies/suggestions/criticisms/etc since that sort of discussion is not allowed in the articles forum.

I agree completely, sorry if not clear; it's much more useful for future readers once the "discussion" has been captured here. My suggesition is just that; compose and discuss here, intereacting with folks to capture the most common questions and answers on this topic, and once "complete", move it to a (general or Prime-dedicated) Articles forum so new users seeking instruction can find it easily.

And thanks for conducting class here, it's very helpful.

--Bob Prosperi
Find all posts by this user
Quote this message in a reply
02-23-2015, 05:21 PM
Post: #8
RE: HP Prime CAS programming
(02-19-2015 08:41 PM)salvomic Wrote:  Thank you, Han,
I'm bookmarking this guide, very interesting for me.

Please, explain also something about how pass arguments, i.e how pass an optional argument...

Have a nice day!

***
EDIT:
please, Han, advise, if possible, how to make a Help for a customized program.
I would like to help about the list of parameters when the program start (or pressing Help key, but I don't know if it's possible)...

One way is to mimic commands from *nix environments. Create a CAS program that acts as a wrapper for the program. The CAS program should handle dynamic input so that if no input is given, it spits out the help. Otherwise, the wrapper sends it to the actual program.

Code:

#cas
wrapper(arg):=
BEGIN
  local s;
  s:=SIZE(arg);
  IF s==0 THEN RETURN("Usage: command(matrix, real, list)"); END;
  IF s==3 THEN DOMYPROG(arg(1),arg(2),arg(3)); END;
  // etc.
END;
#end

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
03-30-2015, 04:29 PM
Post: #9
RE: HP Prime CAS programming
Thanks Han!

This is one of the reasons the Prime is unusable as a reliable and time saving tool, extremely inconsistent and unintuitive handling and results.

Have been trying to make something work that I have spent hours trying to solve before.. Would you please show me how to use "quorem" using arguments in a nonCAS program? Would be REALLY helpful!

Like (this obviously don't work..):

EXPORT TEST(x,y)
BEGIN
CAS.quorem(x,y);
END;
Find all posts by this user
Quote this message in a reply
03-30-2015, 05:46 PM
Post: #10
RE: HP Prime CAS programming
(03-30-2015 04:29 PM)pr0 Wrote:  Thanks Han!

This is one of the reasons the Prime is unusable as a reliable and time saving tool, extremely inconsistent and unintuitive handling and results.

Have been trying to make something work that I have spent hours trying to solve before.. Would you please show me how to use "quorem" using arguments in a nonCAS program? Would be REALLY helpful!

Like (this obviously don't work..):

EXPORT TEST(x,y)
BEGIN
CAS.quorem(x,y);
END;

This works fine when I try TEST([1,2,3,4],[-1,2]). However, it seems that quorem() is broken when using double-quoted arguments such as:

quorem("x^3+2*x^2+3*x+4","-x+2")

My suspicion is that both vectors and strings are pointer-based, and the parser is probably mis-interpreting the string as a vector (I get [undef] as the result). I think you may have found a bug either in the CAS parser or the quorem command itself.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
04-16-2017, 08:46 AM
Post: #11
RE: HP Prime CAS programming
Una publicación en Español fuera del foro: Programación CAS

Viga C | TD | FB
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)