13071 Reputation

29 Badges

11 years, 174 days

On google groups. (comp.soft-sys.math.maple and sci.math.symbolic)

On stackoverflow.


MaplePrimes Activity

These are answers submitted by acer

That's just numeric roundoff error. Your Matrices have entries on the order of 10^19, and that final Norm value is small roundoff noise.

If you want Aa with shape=symmetric indexing function then you could make it so yourself:

  Aa := Matrix(Aa,shape=symmetric,datatype=float[8]):

It's not a big deal but I notice that Mt is datatype=complex[8]. You might make it float[8] to get rid of the 0.0*I fluff.

Another choice is just to increase the working precision (Digits), but of course there's a slowdown when you move from hardware to software floats.

Another choice is to rescale your data (and saving the scaling coefficient for later adjustment as needed, naturally). Eg,

Kk := Kk/max(map(abs, Kk));


For symbolic Matrix inversion Maple will use two kinds of simplifying call.

One is Testzero, which is used to guard against inadvertently selecting a "hidden zero" as a pivot. Choosing as a pivot -- and dividing by -- an expression which could actually simplify to zero would make the answer an evaluation time bomb. By default Testzero uses Normalizer.

The other is Normalizer which is used when reducing a row, in order to keep expression swell down. Linearsolve first checks whether this has been changed from being identical to the `normal` procedure. If so it uses it as is. If not then it tries a little to figure out what might be appropriate (e.g. radnormal, evala, simplify (...,trig), or 'simplify' as larger bore gun).

[edit: ...cont'd] Sometimes LinearSolve will pass off to `solve` or `SolveTools`, but it mostly does similar things with Normalizer.

If you effectively "turn off" Normalizer by setting it to, say x->x then sometimes symbolic/exact LinearSolve can become considerably faster. Potentially dangerously faster as then it may divide by a pivot whose expression would be exact zero if simplified, leading to an invalid result and a division by zero error later.

If you change Normalizer then by default consequence you change Testzero. But in general one still needs zero-testing of candidate pivots, so better to change both separately in the case that Normalizer is being disabled.

Only you will know what you might want for normalizing across the row while pivoting, depending on your example. It can help in final result size, and in practice it can help with speed because adequate zero-testing for pivot selection can slow down if all the candidates have grown enormously complicated.

Another aspect of choice is in how to choose between candidate pivots. It's not possible in general to know which might lead to the simplest result (without trying everything, which is combinatorically impractical). In the exact case you could select according to expression `length` (naive), leaf-count, types of subexpressions, etc.

So you might try experimenting with adjusting Normalizer and Testzero, and/or using similar in your own code.

Why not use the ImportMatrix command?

I copied and rearranged elements of your sample line, to get a two-line file. The following handled both as expected, using Maple 2016.

ImportMatrix("foo.txt", source=csv);

Also, using your call to readline, how about following that with,


Since you attempted it using piecewise, here's an alternate way to handle this example. (It's just for fun, since Carl's suggestion to use plots:-inequal is more straightforward.)


f := x -> -x^2+3*x+2:
l := x -> 4*x:
m := x -> 2*x-4:

P1 := min(f(x), l(x)):
P2 := max(m(x), 0):
plots:-shadebetween(piecewise(P1 > P2, P1, undefined),
                    piecewise(P1 > P2, P2, undefined),
                    x = -1 .. 4, view = -5 .. 10);


[edit] For those with older versions without the modern plots:-shadebetween or plots:-inequal functionality, an old technique (shown by Alec Mihailovs and Robert Israel if I recall) can also be used:

f := x -> -x^2+3*x+2:
l := x -> 4*x:
m := x -> 2*x-4:
P1 := min(f(x), l(x)):
P2 := max(m(x), 0):
fcn1 := piecewise(P1 > P2, P1, undefined):
fcn2 := piecewise(P1 > P2, P2, undefined):
  plot([f,l,m,0],-1 .. 4),
    unapply([x,y+fcn2],x,y))(plot(fcn1-fcn2,x=-1 .. 4,

In my Maple 2016 both of the following produce 0 exactly.


It's actually easier if you you just write that data out to a Matrix, using just the 3rd column of your original. (The first two columns indicate regular spacing, which is so easy to handle that there's no need to store it.)

Are you hoping for a log-scale or one or both axes? That would make it a bit more challenging. Also, labelled contour lines need some extra effort.

Anyway, here's something. Is it on the right track? (I used Maple 2016 for this. If you have only Maple 18 then the surfdata example that used valuesplit in the colorscheme won't work. But the rest does, including this contour plot below.)

That made this (and also some surfdata plots, whose blurry rendering due to the coarseness of the data sample is harder to deal with):

Is the op command what you're after?


eqn1:= (1/2)*p+1+(-4*p^2-p-1)/(3*p^3+7*p^2+2*p+2):

See also the nops command.

Is this similar to what you want? (I used Maple 2016.1, but it also seems ok in Maple 2015.2)

The idea is to build up the assignment statement (using colon-equals) as a string, and then to parse that (without evaluation).

A 3-D plot with a smooth edge can be obtained relatively simply here with:

       x=-sqrt(-y^2+4)..sqrt(-y^2+4), y=-2..2);

You could also get a smooth edge using a polar form (without having to go to a so-called parametric calling sequence of the plot3d command). Eg,

                    polar );

You can figure out that range for `r` by examining:


As Kitonum mentioned, you can use the plots:-display command to show several plots together. Eg,




expr := x^2+y^2-2*y+1:

Psurf := plot3d(expr,

#expr_polar := changecoords(expr,[x,y],polar,[r,t]);
#Psurf := plots:-changecoords(plot3d(expr_polar,
#                                    r=0..2,t=0..2*Pi),
#                             polar):

Pdisk := transform((x,y)->[x,y,0])(disk([0,0],2)):

Pcyl := plot3d(2,t=0..2*Pi,z=0..9,color=green,

Ppt := pointplot3d([0,1,0],color=red,



If you are willing to restrict yourself to the case of a plot inside a PlotComponent then you can use that component's functionality to detect and act upon hover-over.

Here's a simple example.

The information is not a popup per se, but is capable of dynamically revealing/hiding itself. More complicated examples are possible, of course. (I also tried having it dynamically set the component's tooltip, but unfortunately the GUI's revealing of the tooltip was too erratic to be useful in that capacity.)

The code is accessible by right-clicking on the component and, via the menu, looking at its Action code related to hover events.

The Component has properties such that the default manipulator is click&drag, and the plot's manipulator is set to click&drag. I forget whether both of those always survive re-opening a sheet in all recent versions.

By keeping the book a constant height while "rolling" those bodies in your posted video are indicating that they have constant width.

That's not the "Gomboc" shape, as far as I am aware, and I don't understand why you would use that term here.

See this old mapleprimes posting about such 3D shapes.

What I see at the start of your video , rolling under the book, looks to me almost like the revolution of a Reuleaux triangle. I say "almost" because those in the video show a smooth top while the revolution of a Reuleaux triangle has a cusp at its top. There is also an animated MathApp for that in recent Maple versions (and on the maplecloud).

That old mapleprimes posting I cite discusses three shapes in particular: the revolution of a Reuleaux tetrahedron, the Reuleaux tetrahedron, and the Meissner tetrahedron. The shapes in your video appear to me to be bodies of revolution, and to have constant width, which is why I suspect that they may be a variant of the first of these three.

You could try and construct a customized caption instead of a legend, using the technique in my answer here.

Or you could just fake it by using another dummy plot with the legend you want. Eg,

plots:-display( plot( sin(x), x=-Pi..Pi, color="Red",
                      style=pointline, legend="",
                      numpoints=20, adaptive=false ),
                plot( [[0,0]], style=point, legend="sin(x)" ) );

The problem is in how your `f*g` evaluates under evalhf (which plot uses by default when Digits=10 and UseHardwareFloats=deduced ).


You can work around this by either setting Digits greater than 15 (ie. greater than evahf(Digits) ) or, if you do not wish to incur the additional overhead of a higher working precision, setting UseHardwareFloats to be false. Ie,


Another way (which may happen to work here but might not in general...) is to massage the expression so that very large and very small multiplicative terms (each outside of the double precision range, but whose product isn't) don't occur. For example,

`f*g`:= unapply(
          x) assuming x>0, x<0.005:

Yet another approach is to try and switch from symbolic int(..) to approximate evalf(Int(...)), as long as the integrand doesn't suffer the same issue. But then you have to worry about whether the quadrature tolerance will need adjusting, or will work across the whole x-range.

The key command below is,

sort(foo, order=plex(a,b,c));


plots:-setoptions(size=[500, 200], gridlines=false);

# The internal SUM dag gets this order (due to this being
# the "first" time this subexpression is created.
# Your session's computations may have produced this
# combination at some earlier juncture.

expr := (c+b+a)/a;


# The same (the expression is uniquified wrt to internal
# memory) That is to say, the same issue you see with
# plot labels affects regularly output as well.

foo := (a+b+c)/a;


# In fact the structure of the expression reflects the
# order you see in output above.

op( numer( foo ) );

c, b, a


      NAME(4): c
      INTPOS(2): 1
      NAME(4): b
      INTPOS(2): 1
      NAME(4): a
      INTPOS(2): 1
   INTPOS(2): 1
   NAME(4): a
   INTNEG(2): -1

plot(sin(x), x=-Pi..Pi,
     caption = typeset((a+b+c)/a));

plot(sin(x), x=-Pi..Pi,

# The following command re-orders the internal
# structure (SUM dag). This has a global effect, since
# Maple only stores one instance of the sum of terms
# a,b,c in memory.
# Once you do this the new order is seen in both regular
# output as well as in the typeset plot label.

sort(foo, order=plex(a,b,c));


# The same (the expression is uniquified wrt to
# internal memory)



# In fact the structure of the expression reflects
# the order you see in output above. Notice how this
# is different from when this command was issued
# before the customized `sort` call.

op( numer( foo ) );

a, b, c


      NAME(4): a
      INTPOS(2): 1
      NAME(4): b
      INTPOS(2): 1
      NAME(4): c
      INTPOS(2): 1
   INTPOS(2): 1
   NAME(4): a
   INTNEG(2): -1

# The same (the expression is uniquified wrt to
# internal memory)



plot(sin(x), x=-Pi..Pi,

# You can also build your expression up in a specific
# form by using the InertForm package.

plot(sin(x), x=-Pi..Pi,
     labels=[x,InertForm:-Display(`%/`(`%+`(b,a,c),a), inert=false)]);







First let's consider your Question 2), ie. how to measure the length of the string, in the sense of the number of characters that will be displayed.


If you convert your string to bytes then you'll see that the accented e becomes the pair 195, 169.


s := "dégénéré";




B := convert(s,bytes);

[100, 195, 169, 103, 195, 169, 110, 195, 169, 114, 195, 169]




See an ASCII table at this URL.


So you could create your own command to compute character length (width). It could convert to `bytes` and then walk the list to do a count. When it found valid pairs above 127 (which represented a single character) then it could take that into account while counting.


Note that the decimal pair 195 169 also has a Unicode representation with decimal 233. I don't see how this helps especially, though. You can print that unicode entity in the Standard GUI, but its length (alone) is 6.







As for Question 1) which includes printing in bold, your can get that programmatically for use with the print command by forming a piece of so-called TypeMK, which is name which represents a format somewhat similar to MathML.


But I don`t understand what you mean about managing the characters with the printf command. You even made a claim about selecting some text and using the B button from the menubar. But I suspect that you didn`t do that with the displayed result from printf. I don`t really understand what it would mean to manage the display of characters from a printf call. However, if you mentioned printf mostly because of the way it allows you to format and assemble the text then you might note that you could stil use sprintf or nprintf to form key parts (which needed the length metric), even if the final conglomeration is displayed using just print.


bolden:=(s::string)->cat(`#mn("`,s,`",fontweight = "bold")`):

sb := bolden(s);

`#mn("dégénéré",fontweight = "bold")`


`#mn("dégénéré",fontweight = "bold")`




printf("%a", sb);

#mn("dégénéré",fontweight = "bold")

`#mn("dégénéré",fontweight = "bold")`;
`#mi("dégénéré",fontweight = "bold")`;
`#mn("dégénéré",fontweight = "bold", mathcolor = "black")`;
`#mn("dégénéré",fontweight = "normal", mathcolor = "black")`;

`#mn("dégénéré",fontweight = "bold")`

`#mi("dégénéré",fontweight = "bold")`

`#mn("dégénéré",fontweight = "bold", mathcolor = "black")`

`#mn("dégénéré",fontweight = "normal", mathcolor = "black")`


And here is another way (for use with print, not printf ). This also allows for the font size and the font family (if available) to be specified.


Typesetting:-mn("dégénéré",fontweight = "bold", size="18");


Typesetting:-mn("dégénéré", fontweight = "bold", size = "18")

Typesetting:-mn("dégénéré", fontfamily="DejaVu Sans", fontweight = "bold", size = "18");







Did you mention printf because you wanted such formatted output to be left-aligned in the worksheet?




1 2 3 4 5 6 7 Last Page 1 of 137