source: git/Singular/LIB/surfex.lib @ 342394

spielwiese
Last change on this file since 342394 was 342394, checked in by Hans Schönemann <hannes@…>, 17 years ago
*** empty log message *** git-svn-id: file:///usr/local/Singular/svn/trunk@10185 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 48.8 KB
Line 
1//last change: 2007/07/06 (Oliver Labs)
2///////////////////////////////////////////////////////////////////////////////
3version="$Id: surfex.lib,v 1.1 2007-07-09 12:52:50 Singular Exp $";
4category="Visualization";
5info="
6LIBRARY: surfex.lib
7         Procedures for Visualizing Surfaces.
8         This is still an alpha version! Please, send me any comments
9         or suggestions via http://www.AlgebraicSurface.net
10         Thank you!!!
11AUTHOR: Oliver Labs
12        This library uses the program surfex.
13        surfex is written by Oliver Labs and others,
14        mainly Stephan Holzer.
15        It is based on some other tools, mainly
16        surf which was written by Stefan Endrass and others.
17        Some of the code is based on the code in surf.lib
18
19NOTE:
20 Many procedures of this library require the program surfex
21 to be installed.
22 This software is used for producing raytraced images of the surfaces.
23 You can download @code{surfex} from @uref{http://www.surfex.AlgebraicSurface.net}.
24
25 surfex is a front-end for surf which aims to be easier to use than
26 the original tool. In the future, we plan to extend it to a tool which
27 can use other appropriate programs for producing the best visualization.
28 Please, contact me via @uref{http://www.surfex.AlgebraicSurface.net}
29 if you have any questions or suggestions,
30
31 Oliver Labs
32
33PROCEDURES:
34proc plotRotated(poly p, list coords, list #)
35               Plot the surface given by the polynomial p
36               with the coordinates coords.
37proc plotRot(poly p, list #)
38               Similar to plotRotated, but tries to guess automatically
39               which coordinates should be used.
40proc plotRotatedList(list varieties, list coords, list #);
41               Plot the varieties given by the list varieties
42               with the coordinates coords.
43proc plotRotatedDirect(list varietiesList, list #);
44               Plot the varieties given by the list varietiesList.
45               varietiesList has a complicated format.
46               The procedure passes the data directly to surfex.
47               Thus, the coordinates have to be x,y,z.
48               Parameters are allowed; their names have to be p1, p2, ...
49proc plotRotatedListFromSpecifyList(list varietiesList, list #) ;
50               Plot the varieties given by the list varietiesList.
51               varietiesList has a complicated format; see the example.
52";
53
54LIB "solve.lib";
55LIB "primdec.lib";
56LIB "sing.lib";
57
58///////////////////////////////////////////////////////////
59//
60// the main procedures:
61//
62
63proc plotRot(poly p, list #)
64"
65USAGE: plotRot(poly p, list #)
66Similar to plotRotated, but tries to guess automatically
67which coordinates should be used.
68
69It opens the external program surfex for drawing the surface given by p,
70seen as a surface in the real affine space with coordinates coords.
71
72RETURN: the return code of the system command which executes surfex.
73
74ASSUME: The basering is characteristic zero and without parameters.
75"
76{
77    list coords = list();
78    if(num_vars_id(p)==3)
79    {
80        execute("coords = "+string_of_vars(p)+";");
81    }
82    elses
83    {
84        if(num_vars_id(p)<3)
85        {
86            if(nvars(basering)==3)
87            {
88                execute("coords = "+varstr(basering)+";");
89            }
90            else
91            {
92                if(nvars(basering)<3) {
93                    "Could not guess the coordinates because the number of variables in the basering is smaller than 3!";
94                    "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly.";
95                    return(0);
96                } else {
97                    "Could not guess the coordinates because the number of variables in the polynomial is smaller than 3 and the number of variables in the basering is greater than three!";
98                    "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly.";
99                    return(0);
100                }
101            }
102        } else {
103            "Could not guess the coordinates because the number of variables in the polynomial is greater than 3!";
104                    "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly.";
105            return(0);
106        }
107    }
108    return(plotRotatedList(list(p), coords, #));
109}
110example {
111    "Example:"; echo=2;
112
113    // More variables in the basering, but only 3 variables in the polynomial:
114    ring r1 = 0, (w,x,y,z), dp;
115    poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3;
116    plotRot(cayley_cubic);
117
118    // Three variables in the basering, but fewer variables in the polynomial:
119    ring r2 = 0, (x,y,z), dp;
120    plotRot(x^2+y^2-1);
121    plotRot(y^2+z^2-1);
122
123    // A cubic surface with a solitary point:
124    // Use the additional parameter 3 to ask singular
125    // to compute the singular locus before calling surfex.
126    ring r3 = 0, (x,y,z), dp;
127    poly kn_10 = x^3-3*x*y^2+z^3+3*x^2+3*y^2+z^2;
128    plotRot(kn_10, 3);
129
130    // The swallowtail:
131    // a surface with a real solitary curve sticking out of the surface.
132    // Use the additional parameter 3 to ask singular
133    // to compute the singular locus before calling surfex.
134    poly swallowtail = -4*y^2*z^3-16*x*z^4+27*y^4+144*x*y^2*z+128*x^2*z^2-256*x^3;
135    plotRot(swallowtail, 3);
136}
137
138proc plotRotated(poly p, list coords, list #)
139"
140USAGE: plotRotated(poly p, list coords, list #)
141This opens the external program surfex for drawing the surface given by p,
142seen as a surface in the real affine space with coordinates coords.
143
144RETURN: the return code of the system command which executes surfex.
145
146ASSUME: coords is a list of three variables.
147The basering is characteristic zero and without parameters.
148"
149{
150    return(plotRotatedList(list(p), coords, #));
151}
152example {
153    "Example:"; echo=2;
154
155    // An easy example: a surface with four conical nodes.
156    ring r = 0, (x,y,z), dp;
157    poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3;
158//     plotRotated(cayley_cubic, list(x,y,z));
159
160    // An difficult example: a surface with a one-dimensional real component!
161    poly whitney_umbrella = x^2*z-y^2;
162    // The Whitney Umbrella without its handle:
163    plotRotated(whitney_umbrella, list(x,y,z));
164    // The Whitney Umbrella together with its handle:
165    plotRotated(whitney_umbrella, list(x,y,z), 2);
166}
167
168
169proc plotRotatedList(list varieties, list coords, list #)
170"
171USAGE: plotRotatedList(list varieties, list coords, list #)
172This opens the external program surfex for drawing the surfaces given by varieties,
173seen as a surface in the real affine space with coordinates coords.
174
175RETURN: the return code of the system command which executes surfex.
176
177ASSUME: coords is a list of three variables,
178varieties is a list of ideals discribing the varieties to be shown.
179The basering is characteristic zero and without parameters.
180"
181{
182    def oring = basering;
183
184    int plotquality = 0;
185    if(size(#)>0) {
186        plotquality = #[1];
187    }
188
189    list varietiesList = list(list(), list(), list(), list());
190    list usedSurfaces = list();
191    list curveColors = list();
192
193    // go through the list of varieties
194    // produce a list which can be used as input for plotRotatedListFromList()
195    int i;
196    int j;
197    list indList;
198    int ind;
199    ideal itmp;
200    int ncurves;
201    list pd;
202    int k;
203    int surfind;
204    list curSurfColors = list();
205
206    list listOfPoints = list();
207    string str_I = "";
208
209    for(i=1; i<=size(varieties); i++) {
210        itmp = varieties[i];
211        if(plotquality>=3) {
212            itmp = radical(itmp);
213        }
214        itmp = simplify(itmp,1);
215        itmp = simplify(itmp,2);
216        if(size(itmp)==1) { // i.e.: a surface given by one equation
217            surfind = findInList(surfEqn(itmp[1],coords), usedSurfaces);
218            if(surfind==0) {
219                usedSurfaces = usedSurfaces + list(surfEqn(itmp[1],coords));
220                curSurfColors = list(list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)),
221                                     list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1)));
222                varietiesList[1] = varietiesList[1] +
223                    list(list(list("eqno:",string(size(varietiesList[1])+1)),
224                              list("equation:",surfEqn(itmp[1], coords)),
225                              curSurfColors[1],
226                              curSurfColors[2],
227                              list("showcbox:","true"),
228                              list("transparency:","0")));
229                surfind = size(varietiesList[1]);
230
231            }
232            if(plotquality==1) {
233                varieties = varieties + list(slocus(itmp[1]));
234            }
235            if(plotquality==2 || plotquality==3) {
236                // remove doubled components and
237                // add the 1-dimensional singular components
238                // of the surface to the list of curves:
239                int dsl = dim_slocus(itmp[1]);
240                dsl;
241                if(dsl>=0) { // i.e. there is a singular locus
242                    "compute singular locus...";
243                    list eqd;
244                    //
245                    eqd = equidim(slocus(itmp[1]));
246                    ideal tmp_l;
247                    tmp_l = std(eqd[size(eqd)]);
248                    "dim:",dim(tmp_l);
249                    if(dim(tmp_l)==(nvars(basering)-3+2)) {
250                        "--- 2-dim.";
251                        // we have found a multiple component;
252                        // replace it by a simple copy of it
253                        itmp = quotient(itmp[1], tmp_l);
254                        varieties[i] = itmp[1];
255                        eqd = delete(eqd,size(eqd));
256                        if(size(eqd)>0) {
257                            tmp_l = std(eqd[size(eqd)]);
258                        }
259                    }
260                    if(dim(tmp_l)==(nvars(basering)-3+1)) {
261                        "--- 1-dim.";
262                        // we have found a 1-dimensional singular locus
263                        pd = std_primdecGTZ(tmp_l,2);
264                        for(k=1; k<=size(pd); k++) {
265                            if(pd[k][3]==(nvars(basering)-3+1)) {
266                                varieties = varieties + list(pd[k][2]);
267                                curveColors[size(varieties)] = curSurfColors;
268                            } else {
269                                "???";
270                            }
271                        }
272                        eqd = delete(eqd,size(eqd));
273                        if(size(eqd)>0) {
274                            tmp_l = std(eqd[size(eqd)]);
275                        }
276                    }
277                    if(dim(tmp_l)==(nvars(basering)-3+0)) {
278                        "--- 0-dim.";
279                        // we have found a 0-dimensional singular locus
280                        // we compute floating point approximations of the
281                        // coordinates of all singular points
282                        if(npars(oring)>0) {
283                            "str:",parstr(1),rootminpoly();
284                            list all_real_sols = allroots_minpoly();
285//                            "all sols:";all_real_sols;
286//                            sprintf("number %s = %s; ", parstr(1), rootminpoly());
287                            int minp;
288                            if((npars(basering) == 1) && (minpoly != 0)) {
289                                minp = 1;
290                            } else {
291                                minp = 0;
292                            }
293                            str_I = "";
294                            if(minp==1) {
295                                "minp=1";
296                                string str_para = parstr(1);
297                                string str_tmp_l;
298                                def cur_ring = basering;
299                                if(1) {
300                                    short=0;
301                                    str_tmp_l = "ideal eqd_tmp = "+
302//                                        string(tmp_l)+","+string(minpoly)+";";
303                                        string(tmp_l);
304                                    "str:",str_tmp_l;
305                                    string str_num_mp = "number "+parstr(1)+"="+
306                                        decstr2ratstr(rootminpoly())+";";
307                                    execute("ring Iring = 0,("
308//                                            +string(coords)+","+str_para+"),dp;");
309                                            +string(coords)+"),dp;");
310                                    basering;
311                                    execute(str_num_mp);
312                                    execute(str_tmp_l);
313                                    eqd_tmp;
314                                    list real_sols = real_solve(eqd_tmp);
315                                    real_sols;
316                                    $;
317                                    setring cur_ring;
318                                }
319                            } else {
320                                // minp==0: we do not know how to handle this
321                                "???";
322                            }
323                        } else {
324                            "no pars";
325                            ideal eqd_tmp = tmp_l;
326                            short=0;
327                            string str_tmp_l = "ideal eqd_tmp = "+string(tmp_l)+";";
328                            def cur_ring = basering;
329                            execute("ring Iring = (real,30),("+string(coords)+"),("+ordstr(oring)+");");
330//                            basering;
331                            execute(str_I);
332                            execute(str_tmp_l);
333                            list real_sols = real_solve(eqd_tmp);
334                            setring cur_ring;
335                        }
336                        "real_sols:";real_sols;
337                        for(k=1; k<=size(real_sols); k++) {
338                            "search point:";
339                             string(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind)));
340//                             listOfPoints;
341                            if(findInList(string(list(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind)))),
342                                          listOfPoints)==0) {
343                                "add pt";
344                                varietiesList[4] = varietiesList[4] +
345                                    list(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind)));
346                                listOfPoints = listOfPoints +
347                                    list(string(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind))));
348                            }
349                        }
350                    }
351                }
352            }
353        } else {
354            // i.e.: more than one equation
355            varietiesList[2] = varietiesList[2] +
356                list(list(list("surfaces:"),
357                          list("curveno:",
358                               string(size(varietiesList[2])+1)),
359                          list("showcbox:","true")));
360            if(size(curveColors) >= i) {
361                varietiesList[2][size(varietiesList[2])][4] = curveColors[i][1];
362                varietiesList[2][size(varietiesList[2])][4][1] = "color:";
363            }
364            ncurves = size(varietiesList[2]);
365            for(j=1; j<=size(itmp); j++) {
366                ind = findInList(surfEqn(itmp[j],coords), usedSurfaces);
367                usedSurfaces = usedSurfaces + list(surfEqn(itmp[1],coords));
368//                "indList:";indList;
369                if(ind == 0) {
370//                    "--------> not in list", surfEqn(itmp[j], coords);
371                    if(j==1) {
372                        varietiesList[1] = varietiesList[1] +
373                            list(list(list("eqno:",string(size(varietiesList[1])+1)),
374                                      list("equation:",surfEqn(itmp[j], coords)),
375                                      list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)),
376                                      list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1)),
377                                      list("showcbox:","true"),
378                                      list("transparency:","100")));
379                    } else {
380                        varietiesList[1] = varietiesList[1] +
381                            list(list(list("eqno:",string(size(varietiesList[1])+1)),
382                                      list("equation:",surfEqn(itmp[j], coords)),
383                                      list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)),
384                                      list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1)),
385                                      list("showcbox:","false"),
386                                      list("transparency:","0")));
387                    }
388                    ind = size(varietiesList[1]);
389                } else {
390                }
391                varietiesList[2][ncurves][1] = varietiesList[2][ncurves][1] + list(string(ind));
392            }
393        }
394    }
395
396//      "------------";
397//      varietiesList;
398//      "------------";
399    return(plotRotatedListFromSpecifyList(varietiesList, coords, #));
400}
401example {
402    "Example:"; echo=2;
403
404    // A cubic surface together with a tritangent plane
405    // (i.e. a plane which cuts out three lines).
406    ring r = 0, (x,y,z), dp;
407    poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3;
408    poly plane = 1-x-y-z;
409    plotRotatedList(list(cayley_cubic, plane), list(x,y,z));
410
411    // The same cubic and plane.
412    // The plane is not shown but only its intersection with the surface.
413    plotRotatedList(list(cayley_cubic, ideal(cayley_cubic, plane)), list(x,y,z));
414}
415
416
417proc plotRotatedListFromSpecifyList(list varietiesList, list #)
418"
419USAGE: plotRotatedListFromSpecifyList(list varietiesList, list #);
420varietiesList has a complicated format (not documented yet);
421see the example.
422
423RETURN: the return code of the system command which executes surfex.
424
425ASSUME: The basering is characteristic zero.
426
427EXAMPLE: example plotRotatedListFromSpecifyList;
428"
429{
430    // make the surfex file
431    string str = getSurfexCodeFromSpecifyList(varietiesList, #);
432
433    return(plotRotatedFromCode(str, #));
434}
435example {
436    "Example:"; echo=2;
437
438    // A cubic surface depending on a parameter:
439    ring r = (0,p1), (x,y,z), dp;
440    poly cayley_cubic = x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3;
441    poly plane = 1-x-y-z;
442    plotRotatedListFromSpecifyList(list(list(list(list("eqno:","1"),
443                                                  list("equation:",
444                                                       string(cayley_cubic))
445                                                 )
446                                            ),
447                                        list(),
448                                        list(list(1,"0.0","1.0","500","0.25+0.25*sin(PI*p1)")),
449                                        list()
450                                       ));
451}
452
453
454proc plotRotatedListFromStringList(list varieties, list #)
455"
456RETURN: the return code of the system command which executes surfex.
457
458USAGE: not documented yet.
459"
460{
461    // make the surfex file
462    getSurfexCodeFromStringList(varieties, #);
463    string str = getSurfexCodeFromStringList(varieties, #);
464
465    return(plotRotatedFromCode(str, #));
466}
467
468
469proc plotRotatedDirect(list varieties, list #)
470"
471USAGE: plotRotatedDirect(list varieties, list #)
472This opens the external program surfex for drawing the surfaces given by varieties,
473seen as a surface in the real affine space with coordinates x,y,z.
474The format for the list varieties is not fully documented yet;
475please, try to adapt the examples to your needs.
476
477RETURN: the return code of the system command which executes surfex.
478
479ASSUME:
480Passes the equations directly to surfex,
481i.e., the variable names should be correct, i.e. x,y,z.
482The advantage is that one can use parameters p1, p2, ...;
483these will be passed to surfex.
484"
485{
486    string str = getSurfexCodeFromListDirect(varieties, #);
487
488    return(plotRotatedFromCode(str, #));
489}
490example {
491    "Example:"; echo=2;
492
493    // A cubic surface depending on a parameter:
494    ring r = (0,p1), (x,y,z), dp;
495    poly cayley_cubic = x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3;
496    // The entries of the list of varieties can either be polynomials
497    plotRotatedDirect(list(list(list(cayley_cubic)),
498                           list(),
499                           list(list(1,"0.0","1.0","500","0.25+0.25*sin(PI*p1)"))
500                           ));
501
502    // or strings which represent surfex-readable polynomials
503    plotRotatedDirect(list(list(list("x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3")),
504                           list(),
505                           list(list("1","0.0","1.0","500","0.25+0.25*sin(PI*p1)"))
506                           ));
507
508    // More complicated varieties
509    plotRotatedDirect(list(list(list("x^2+y^2-z^2-3^2"),
510                                list("x*sin(p1)+y*cos(p1)-3")),
511                           list(list(list(1,2))),
512                           list(list("1","0.0","1.0","500","2*PI*p1"))
513                           ));
514}
515
516proc plotRotatedFromCode(string str, list #)
517"
518USAGE: plotRotatedFromCode(string str, list #);
519
520This procedure is only for internal usage;
521it takes the surfex-code as a string and calls surfex.
522
523RETURN: the return code of the system command which executes surfex.
524"
525{
526     // we need a temporary .sux file for surfex
527    string tmpd = "/tmp";
528    string l="surf"+string(system("pid"))+".sux";
529    // a temporary file which stores the output of surfex
530    string erg="/tmp/surferg"+string(system("pid"));
531
532    write(":w "+tmpd+"/"+l, str);
533
534    string surfex_path=system("Singular");
535    while(surfex_path[size(surfex_path)]!="/") { surfex_path=surfex_path[1..size(surfex_path)-1]; }
536    surfex_path=surfex_path+"../LIB/surfex";
537
538    int i=system("sh","surfex \""+surfex_path+"\" -d "+tmpd+" -i " + l +" >"+erg+" 2>/dev/null");
539
540    // delete the temporary file
541    i = system("sh","rm " + l +" 2>/dev/null");
542    return(read(erg));
543}
544
545
546///////////////////////////////////////////////////////////
547//
548// procedures used to produce the surf-code:
549//
550
551
552proc getSurfexCodeFromListDirect(list varieties, list #)
553"
554USAGE: getSurfexCodeFromListDirect(list varieties, list #)
555
556ASSUME: varieties has four components,
557        - the first is a list of polynomials, say f_1, ..., f_k
558        - the second is a list of lists of numbers in {1, ..., k} describing the curves
559          as intersections of the corresponding f_i
560        - the third is a list of lists describing the parameters used in the polynomials f_i
561        - the fourth is a list of lists of points given by their approximate coordinates (three decimal numbers)
562
563RETURN: the surfex code (.sux)
564"
565{
566    int i;
567    int j;
568    string str = "this is surfex v0.89.07"+newline;
569
570    str = str + "TYPE:" + newline;
571    str = str + "specify"+newline;
572    str = str + "EQUATIONS:"+newline;
573    str = str + string(size(varieties[1])) + newline;
574    for(i=1; i<=size(varieties[1]); i++) {
575        str = str + "Equation:"+newline;
576        str = str + "eqno:"+newline;
577        str = str + string(i) + newline;
578        str = str + "equation:"+newline;
579        str = str + surfEqnDir(varieties[1][i][1]) + newline;
580        if(size(varieties[1][i])>=2) {
581            str = str + "showcbox:"+newline;
582            str = str + varieties[1][i][2] + newline;     // show it or not
583            if(size(varieties[1][i])>=3) {
584                str = str + "transparency:"+newline;
585                str = str + string(varieties[1][i][3]) + newline;     // transparency
586            }
587        }
588    }
589    str = str + "CURVES:"+newline;
590    str = str + string(size(varieties[2])) + newline;
591    for(i=1; i<=size(varieties[2]); i++) {
592        str = str + "Curve:"+newline;
593        str = str + "curveno:"+newline;
594        str = str + string(i) + newline;
595        str = str + "surfaces:"+newline;
596//        "curves:";varieties[2][i];
597        for(j=1; j<=size(varieties[2][i][1]); j++) {
598            str = str + string(varieties[2][i][1][j]) + newline;
599        }
600        if(size(varieties[2][i])>=2) {
601            str = str + "showcbox:"+newline;
602            str = str + varieties[2][i][2] + newline;     // show it or not
603        }
604    }
605    str = str + "PARAMETERS:"+newline;
606    str = str + string(size(varieties[3])) + newline;
607    for(i=1; i<=size(varieties[3]); i++) {
608        str = str + "Parameter:"+newline;
609        str = str + "parno:"+newline;
610        str = str + string(varieties[3][i][1]) + newline;
611        str = str + "fromtoval:"+newline;
612        str = str + varieties[3][i][2] + newline;
613        str = str + varieties[3][i][3] + newline;
614        str = str + string(varieties[3][i][4]) + newline;
615        if(size(varieties[3][i])>=5) {
616            str = str + "function:"+newline;
617            str = str + varieties[3][i][5]+newline;
618        }
619    }
620//     str = str + "////////////////// Parameter: /////////////////////////"+newline;
621//     str = str + "1" + newline;
622//     str = str + "0.0" + newline;
623//     str = str + "1.0" + newline;
624//     str = str + "1000" + newline;
625//    str = str + string(size(varieties[3])) + newline;
626    return(str);
627}
628
629proc getSurfexCodeFromList(list varieties, list coords, list #)
630"
631ASSUME: varieties has four components,
632        - the first is a list of polynomials, say f_1, ..., f_k
633        - the second is a list of lists of numbers in {1, ..., k} describing the curves
634          as intersections of the corresponding f_i
635        - the third is a list of lists describing the parameters used in the polynomials f_i
636        - the fourth is a list of lists of points given by their approximate coordinates (three decimal numbers)
637
638RETURN: the surfex code (.sux)
639"
640{
641    int i;
642    int j;
643    string str = "this is surfex v0.89.07"+newline;
644
645    str = str + "TYPE:" + newline;
646    str = str + "specify"+newline;
647    str = str + "EQUATIONS:"+newline;
648    str = str + string(size(varieties[1])) + newline;
649    for(i=1; i<=size(varieties[1]); i++) {
650        str = str + "Equation:"+newline;
651        str = str + "eqno:"+newline;
652        str = str + string(i) + newline;
653        str = str + "equation:"+newline;
654        str = str + surfEqn(varieties[1][i][1], coords) + newline;
655        str = str + "showcbox:"+newline;
656        str = str + varieties[1][i][2] + newline;     // show it or not
657        str = str + "transparency:"+newline;
658        str = str + string(varieties[1][i][3]) + newline;     // transparency
659    }
660    str = str + "CURVES:"+newline;
661    str = str + string(size(varieties[2])) + newline;
662    for(i=1; i<=size(varieties[2]); i++) {
663        str = str + "Curve:"+newline;
664        str = str + "curveno:"+newline;
665        str = str + string(i) + newline;
666        str = str + "surfaces:"+newline;
667        for(j=1; j<=size(varieties[2][i]); j++) {
668            str = str + string(varieties[2][i][1][j]) + newline;
669        }
670        str = str + "showcbox:"+newline;
671        str = str + varieties[2][i][2] + newline;     // show it or not
672    }
673    str = str + "PARAMETERS:"+newline;
674    str = str + string(size(varieties[3])) + newline;
675    for(i=1; i<=size(varieties[3]); i++) {
676        str = str + "Parameter:"+newline;
677        str = str + "parno:"+newline;
678        str = str + string(varieties[3][i][1]) + newline;
679        str = str + "fromtoval:"+newline;
680        str = str + surfEqn(varieties[3][i][2], coords) + newline;
681        str = str + surfEqn(varieties[3][i][3], coords) + newline;
682        str = str + string(varieties[3][i][4]) + newline;
683        if(size(varieties[3][i])>=5) {
684            str = str + "function:"+newline;
685            str = str + varieties[3][i][5]+newline;
686        }
687    }
688//     str = str + "////////////////// Parameter: /////////////////////////"+newline;
689//     str = str + "1" + newline;
690//     str = str + "0.0" + newline;
691//     str = str + "1.0" + newline;
692//     str = str + "1000" + newline;
693//    str = str + string(size(varieties[3])) + newline;
694    return(str);
695}
696
697proc getSurfexCodeFromStringList(list varieties, list #)
698"
699ASSUME: varieties has three components,
700        - the first is a list of polynomials, say f_1, ..., f_k
701        - the second is a list of lists of numbers in {1, ..., k} describing the curves
702          as intersections of the corresponding f_i
703        - the third is a list of lists describing the parameters used in the polynomials f_i
704
705RETURN: the surfex code (.sux)
706"
707{
708    int i;
709    int j;
710    string str = "this is surfex v0.89.07"+newline;
711
712    str = str + "TYPE:" + newline;
713    str = str + "specify"+newline;
714    str = str + "EQUATIONS:"+newline;
715    str = str + string(size(varieties[1])) + newline;
716    for(i=1; i<=size(varieties[1]); i++) {
717        str = str + "Equation:"+newline;
718        str = str + "eqno:"+newline;
719        str = str + string(i) + newline;
720        str = str + "equation:"+newline;
721        str = str + varieties[1][i][1] + newline;
722        str = str + "showcbox:"+newline;
723        str = str + varieties[1][i][2] + newline;     // show it or not
724        str = str + "transparency:"+newline;
725        str = str + varieties[1][i][3] + newline;     // transparency
726    }
727    str = str + "CURVES:"+newline;
728    str = str + string(size(varieties[2])) + newline;
729    for(i=1; i<=size(varieties[2]); i++) {
730        str = str + "Curve:"+newline;
731        str = str + "curveno:"+newline;
732        str = str + string(i) + newline;
733        str = str + "surfaces:"+newline;
734        for(j=1; j<=size(varieties[2][i][1]); j++) {
735            str = str + string(varieties[2][i][1][j]) + newline;
736        }
737        str = str + "showcbox:"+newline;
738        str = str + varieties[2][i][2] + newline;     // show it or not
739    }
740    str = str + "PARAMETERS:"+newline;
741    str = str + string(size(varieties[3])) + newline;
742    for(i=1; i<=size(varieties[3]); i++) {
743        str = str + "Parameter:"+newline;
744        str = str + "parno:"+newline;
745        str = str + string(varieties[3][i][1]) + newline;
746        str = str + "fromtoval:"+newline;
747        str = str + varieties[3][i][2] + newline;
748        str = str + varieties[3][i][3] + newline;
749        str = str + string(varieties[3][i][4]) + newline;
750        if(size(varieties[3][i])>=5) {
751            str = str + "function:"+newline;
752            str = str + varieties[3][i][5]+newline;
753        }
754    }
755    return(str);
756}
757
758
759proc getSurfexCodeFromSpecifyList(list varieties, list #)
760"
761ASSUME: varieties has three components,
762        - the first is a list of polynomials, say f_1, ..., f_k
763        - the second is a list of lists of numbers in {1, ..., k} describing the curves
764          as intersections of the corresponding f_i
765        - the third is a list of lists describing the parameters used in the polynomials f_i
766        - the fourth is a list of lists describing the singular points to be shown as spheres
767
768RETURN: the surfex code (.sux)
769"
770{
771    int i;
772    int j;
773    int k;
774    string str = "this is surfex v0.89.07"+newline;
775
776    str = str + "TYPE:" + newline;
777    str = str + "specify"+newline;
778    str = str + "EQUATIONS:"+newline;
779    str = str + string(size(varieties[1])) + newline;
780    for(i=1; i<=size(varieties[1]); i++) {
781        str = str + "Equation:"+newline;
782        for(j=1; j<=size(varieties[1][i]); j++) {
783            str = str + varieties[1][i][j][1] +newline;
784            str = str + varieties[1][i][j][2] +newline;
785        }
786    }
787    str = str + "CURVES:"+newline;
788    str = str + string(size(varieties[2])) + newline;
789    for(i=1; i<=size(varieties[2]); i++) {
790        str = str + "Curve:"+newline;
791        for(j=1; j<=size(varieties[2][i]); j++) {
792            str = str + varieties[2][i][j][1] +newline;
793            if(varieties[2][i][j][1] == "surfaces:") {
794                for(k=2; k<=size(varieties[2][i][j]); k++) {
795                    str = str + string(varieties[2][i][j][k]) + newline;
796                }
797            } else {
798                str = str + varieties[2][i][j][2] +newline;
799            }
800        }
801//         str = str + "curveno:"+newline;
802//         str = str + string(i) + newline;
803//         str = str + "surfaces:"+newline;
804//         for(j=1; j<=size(varieties[2][i][1]); j++) {
805//             str = str + string(varieties[2][i][1][j]) + newline;
806//         }
807//         str = str + "showcbox:"+newline;
808//         str = str + varieties[2][i][2] + newline;     // show it or not
809    }
810    str = str + "PARAMETERS:"+newline;
811    str = str + string(size(varieties[3])) + newline;
812    for(i=1; i<=size(varieties[3]); i++) {
813        str = str + "Parameter:"+newline;
814        str = str + "parno:"+newline;
815        str = str + string(varieties[3][i][1]) + newline;
816        str = str + "fromtoval:"+newline;
817        str = str + varieties[3][i][2] + newline;
818        str = str + varieties[3][i][3] + newline;
819        str = str + string(varieties[3][i][4]) + newline;
820        if(size(varieties[3][i])>=5) {
821            str = str + "function:"+newline;
822            str = str + varieties[3][i][5]+newline;
823        }
824    }
825    string str_from = "0.0";
826    string str_to = "5.0";
827    string str_radius = "50";
828    str = str + "SOLITARY POINTS:"+newline;
829    str = str + string(size(varieties[4])) + newline;
830    for(i=1; i<=size(varieties[4]); i++) {
831        str = str + "SolitaryPoint:"+newline;
832        str = str + "solPtNo:"+newline;
833        str = str + string(i) + newline;
834        str = str + "surface:"+newline;
835        str = str + varieties[4][i][4] + newline;
836        str = str + "fromtoval:"+newline;
837        str = str + str_from + newline;
838        str = str + str_to + newline;
839        str = str + str_radius + newline;
840        str = str + "coords:" + newline;
841        str = str + varieties[4][i][1] + newline;
842        str = str + varieties[4][i][2] + newline;
843        str = str + varieties[4][i][3] + newline;
844    }
845    return(str);
846}
847
848///////////////////////////////////////////////////////////
849//
850// procedures for standard colors:
851//
852
853proc numBaseColors()
854"
855USAGE: numBaseColors()
856
857RETURN: the number of predefined surface colors.
858"
859{
860    return(6);
861}
862
863proc baseSurfaceColors(int no)
864"
865USAGE: baseSurfaceColors(int no)
866
867REMARK: There are currently 6=numBaseColors() basic surface colors.
868You can modify them according to your wishes
869by just redefining this procedure in your Singular-script.
870
871If you want more colors, then you also have to redefine numBaseColors() accordingly.
872
873RETURN: a list of three integers describing the RGB values of a color.
874"
875{
876    if(no%numBaseColors()==1) {
877        return(list(240,160,0));
878    }
879    if(no%numBaseColors()==2) {
880        return(list(160,240,0));
881    }
882    if(no%numBaseColors()==3) {
883        return(list(0,160,240));
884    }
885    if(no%numBaseColors()==4) {
886        return(list(240,0,160));
887    }
888    if(no%numBaseColors()==5) {
889        return(list(0,240,160));
890    }
891    if(no%numBaseColors()==0) {
892        return(list(160,0,240));
893    }
894}
895
896proc getInsideColorStr(int no)
897"
898USAGE: getInsideColorStr(int no)
899
900RETURN: a string describing inside color number no
901where the three integer RGB values are in one line each.
902"
903{
904    list bc = baseSurfaceColors(no);
905    string str = string(bc[1])+newline+string(bc[2])+newline+string(bc[3]);
906    return(str);
907}
908
909proc getOutsideColorStr(int no)
910"
911USAGE: getOutsideColorStr(int no)
912
913RETURN: a string describing outside color number no
914where the three integer RGB values are in one line each.
915"
916{
917    list bc = baseSurfaceColors(no);
918    string str = string(bc[1])+newline+string(bc[2])+newline+string(bc[3]);
919    return(str);
920}
921
922///////////////////////////////////////////////////////////
923//
924// procedures used by the plot procedures:
925//
926
927proc surfEqnDir(list #)
928"
929USAGE: surfEqnDir(list #) without any checks etc.
930
931RETURN: string(#[1]) where short=0.
932"
933{
934    int stmp = short; short = 0;
935    string str = string(#[1]);
936    short = stmp;
937    return(str);
938}
939
940proc surfEqn(poly p, list coords, list #)
941"
942USAGE: surfEqn(poly p, list coords)
943       Tries to produce a string for the equation of p which is convenient for surfex.
944ASSUME: - p defines a plane curve or a surface,
945         - coords is a list of the three coordinates to use, e.g. list(x,y,z),
946           in this way, it is possible to distinguish between x^2+y^2-1 and y^2+z^2-1
947RETURN: a string, that one can use with the external program surf
948EXAMPLE: example surfEqn; shows an example
949"
950{
951    int params=0;
952    if(size(#)>0) {
953        params = #[1];
954    }
955    string err_mes; // string containing error messages
956    def base=basering;
957    int mynvars = nvars(basering);
958
959    intvec ind=num_of_vars(p);
960
961    int i,j,n;
962    int minp = 0;
963    n=0;
964    for(i=size(ind);i>0;i--)
965    {
966          if (ind[i]!=0) {
967            n++;
968        } else {
969            if(var(i)==coords[1] || var(i)==coords[2] || var(i)==coords[3]) {
970                ind[i]=1;
971                n++;
972            }
973        }
974    }
975
976    params = params + npars(basering);
977    n = n + npars(basering);
978    if((npars(basering) == 1) && (minpoly != 0)) {
979        minp = 1;
980    } else {
981        minp = 0;
982    }
983    string str_I = "";
984    for(i=1; i<=npars(basering); i=i+1) {
985        if(!(parstr(i) == "i")) {
986            if(minp==1) {
987                str_I = str_I + sprintf("number %s = %s; ", parstr(i), rootminpoly());
988            } else {
989            }
990        }
991    }
992    int bshort = short; short = 0;
993    if(!(minp==1 || npars(basering)==0)) {
994        p=cleardenom(p);
995        err_mes="Cannot plot equations with a parameter without a specified minpoly";
996        ERROR(err_mes);
997    }
998    str_I = str_I + "poly p = " + string(p) + ";";
999
1000    short = bshort;
1001
1002    if(params==0) {
1003        if (n<=2 or n>=4)
1004        {
1005            err_mes="Cannot plot equations with "+string(n)+" variables";
1006            ERROR(err_mes);
1007//            return("0");
1008        }
1009        if(n==4) {
1010            ring r=(real,30,30),(xx,yy,zz,ww),dp;
1011        } else {
1012            ring r=(real,30,30),(x,y,z),dp;
1013        }
1014    } else {
1015        if(n-params<=2 || n-params>=4) {
1016            err_mes="Cannot plot equations with "+string(n-params)+" variables";
1017            ERROR(err_mes);
1018//            return("0");
1019        } else {
1020            if(params == 1) {
1021                if(n-params==3) {
1022                    if(minp==1) {
1023                        // switch to a ring without minimal polynomial:
1024                        execute("ring rr = (real,30,30),("+varstr(base)+"), dp;");
1025//                        rr;
1026//                        "str_I",str_I;
1027                        execute(str_I);
1028                        def base = rr;
1029                        ring r=(real,30,30),(x,y,z),dp;
1030                    } else {
1031                        p=cleardenom(p);
1032                        ring r=(real,30,30),(x,y,z,p1),dp;
1033                    }
1034                }
1035            }
1036            if(params == 2) {
1037                if(n-params==3) {
1038                    p=cleardenom(p);
1039                    ring r=(real,30,30),(x,y,z,p1,p2),dp;
1040                }
1041            }
1042            if(params == 3) {
1043                if(n-params==3) {
1044                    p=cleardenom(p);
1045                    execute("ring rr = (real,30,30),("+varstr(base)+","+parstr(base)+"), dp;");
1046                    rr;
1047                    "str_I",str_I;
1048                    execute(str_I);
1049                    "pnew:",p;
1050                    def base = rr;
1051
1052                    ring r=(real,30,30),(x,y,z,p1,p2,p3),dp;
1053                }
1054            }
1055        }
1056    }
1057//    basering;
1058    short=0;
1059    map phi=base,0;
1060    j=1;
1061
1062    for(i=1;i<=mynvars;i++)
1063    {
1064        if (ind[i]!=0)
1065        {
1066            phi[i]=var(j);
1067            j++;
1068        }
1069    }
1070    poly p=(simplify(phi(p),1));
1071    if (leadcoef(p) <0) {
1072        if(size(#)>1) {
1073            if(#[2]!=0) {
1074                p=-p;
1075            }
1076        } else {
1077            p=-p;
1078        }
1079    }
1080    if(leadcoef(p)!=0) {
1081        p = p/leadcoef(p);
1082    }
1083    string thesurfstr = string(p);
1084    if(minp == 1) {
1085        // replace k by rootRepl
1086    }
1087
1088    return (thesurfstr);
1089} // end of surfEqn()
1090example
1091{ "EXAMPLE:"; echo =2;
1092
1093  ring rr0 = 0,(x(1..3)),dp;
1094  poly p = x(1)^3 - x(2)^2;
1095  print(surfEqn(p,list(x(1),x(2),x(3))));
1096
1097  ring rr1 = 0,(x,y,z),dp;
1098  poly I(1) = 2x2-1/2x3 +1-y+1;
1099  print(surfEqn(I(1),list(x,y,z)));
1100
1101  // Steiner surface
1102  poly J(2) = x^2*y^2+x^2*z^2+y^2*z^2-17*x*y*z;
1103  print(surfEqn(J(2),list(x,y,z)));
1104} // end of example surfEqn()
1105
1106
1107proc num_of_vars(ideal I)
1108"
1109USAGE: num_of_vars(ideal I)
1110
1111RETURN: an intvec containing one entry for each ring variable.
1112each contains the sums of all degrees in this variable of all monomials
1113occuring in the ideal.
1114An entry is zero iff the corresponding variable does not occur in the ideal.
1115"
1116{
1117  intvec v;
1118  int i;
1119  poly p;
1120  for(i=size(I);i>0;i--)
1121  {
1122    p=I[i];
1123    while(p!=0)
1124    {
1125        v=v+leadexp(p);
1126        p=p-lead(p);
1127    }
1128  }
1129  return(v);
1130}
1131example {
1132    "EXAMPLE:"; echo = 2;
1133    ring r = 0, (x,y,z),dp;
1134    ideal j0 = x^2-x*y;
1135    num_of_vars(j0);
1136    ideal j1 = x^2-x*y-y;
1137    num_of_vars(j1);
1138    ideal j2 = x^2-x*y-y, x^3-2*y;
1139    num_of_vars(j2);
1140}
1141
1142
1143proc num_vars_id(ideal I)
1144"
1145USAGE: num_vars_id(ideal I)
1146
1147RETURN: The number of ring-variables occurring in the ideal I.
1148"
1149{
1150    intvec v = num_of_vars(I);
1151    int num = 0;
1152    for(int i=size(v);i>0;i--)
1153    {
1154        if (v[i]!=0) { num++; }
1155    }
1156    return(num);
1157}
1158example {
1159    "EXAMPLE:"; echo = 2;
1160    ring r = 0, (x,y,z),dp;
1161    ideal j = x^2-y, x^3-2;
1162    num_vars_id(j);
1163}
1164
1165proc findInList(list obj, list l)
1166"
1167USAGE: findInList(list obj, list l)
1168       Tries to find the object obj in the list l.
1169
1170ASSUME: the object obj[1] can be compared to the objects in the list l
1171
1172RETURN: if obj[1]=l[i] for some i, then return the first such i,
1173        otherwise return 0
1174"
1175{
1176    for(int i=1; i<=size(l); i++) {
1177        if(l[i]==obj[1]) {
1178            return(i);
1179        }
1180    }
1181
1182    return(0);
1183}
1184example {
1185    "EXAMPLE:"; echo = 2;
1186    ring r = 0,(x,y,z), dp;
1187    list a = list(x^2+y^2+z^2+1, x^2+y^2+z^2-1, x^2+y^2-z^2+1, x^2+y^2-z^2-1);
1188    findInList(x^2+y^2+z^2-1, a);
1189    findInList(x^2+y^2+z^2, a);
1190}
1191
1192proc std_primdecGTZ(ideal I, list #)
1193"
1194USAGE: std_primdecGTZ(ideal I, list #)
1195Computes a primdary decomposition pd of I using primdecGTZ and then
1196calls std_for_pd(pd).
1197For the output and options, consult the help of std_for_pd.
1198
1199RETURN: see std_for_pd.
1200"
1201{
1202    list pd = primdecGTZ(I);
1203    return(std_for_pd(pd, #));
1204}
1205example {
1206    "EXAMPLE:"; echo = 2;
1207
1208    ring r = 0, (x,y), dp;
1209    ideal j = y-x^2,z-x^3;
1210    primdecGTZ(j);
1211    std_primdecGTZ(j);
1212    std_primdecGTZ(j,1);
1213}
1214
1215proc std_for_pd(list pd, list #)
1216"
1217USAGE: std_for_pd(list pd, list #)
1218Call std for each of the prime ideals in the list pd
1219replace the prime ideals by their standard-basis.
1220Compute dim() and mult() of each prime component using these standard bases.
1221If an additional argument is given then do the same for the primary components.
1222
1223ASSUME:
1224pd is in the format produced by primdecGTZ() or primdecSY().
1225
1226RETURN: A list, say l, of lists, similar to a list returned by primdecSY() or primdecGTZ().
1227However, each of the entries of l (which is a list l[i]) contains some additional entries:
1228l[1]: the primary ideal
1229l[2]: a standard basis of the associated prime ideal
1230l[3]: dim() of this prime ideal
1231l[4]: mult() of this prime ideal
1232
1233If an additional argument # is given then l[1] changes:
1234l[1]: a standard basis of the primary ideal
1235Morever, there are some more entries:
1236l[5]: dim() of this primary ideal
1237l[6]: mult() of this primary ideal
1238l[7]: l[6] / l[5]
1239"
1240{
1241
1242    if(typeof(pd[1])=="ideal") {
1243        // this is a Singular bug!?
1244//        "bug!";pd;"---";
1245        pd = list(list(pd[1], pd[1]));
1246//        pd;$;
1247    }
1248    list pd_neu;
1249    int i;
1250    list coords;
1251    ideal stdtmp;
1252    ideal stdtmp2;
1253    for(i=1; i<=size(pd); i++) {
1254        stdtmp = std(pd[i][2]);
1255        stdtmp2 = pd[i][1];
1256        if(size(#)>0) {
1257            stdtmp2 = std(stdtmp2);
1258            if(mult(stdtmp)==0) {
1259                pd_neu[i] = list(stdtmp2,
1260                                 stdtmp,
1261                                 dim(stdtmp), mult(stdtmp),
1262                                 dim(stdtmp2), mult(stdtmp2),
1263                                 0);
1264            } else {
1265                pd_neu[i] = list(stdtmp2,
1266                                 stdtmp,
1267                                 dim(stdtmp), mult(stdtmp),
1268                                 dim(stdtmp2), mult(stdtmp2),
1269                                 mult(stdtmp2)/mult(stdtmp));
1270            }
1271        } else {
1272            pd_neu[i] = list(stdtmp2,
1273                             stdtmp,
1274                             dim(stdtmp), mult(stdtmp));
1275        }
1276    }
1277    return(pd_neu);
1278}
1279example {
1280    "EXAMPLE:"; echo = 2;
1281
1282    ring r = 0, (x,y,z), dp;
1283    ideal j = y-x^2,z-x^3;
1284    list pd = primdecGTZ(j);
1285    pd;
1286    std_for_pd(pd, 1);
1287}
1288
1289proc real_solve(ideal to_solve)
1290"
1291USAGE: real_solve(ideal to_solve)
1292
1293RETURN: a list of all real solutions (as strings)
1294of the zero-dimensional ideal to_solve (without multiplicities).
1295
1296REMARK: Until now, it may happen that some points appear more than once.
1297"
1298{
1299    int k;
1300    int i;
1301
1302//    def Isolring = solve(to_solve,30,0,60,"nodisplay");
1303    def Isolring = solve(to_solve,9,0,13,"nodisplay");
1304    setring Isolring;
1305//    list SOL = solve(to_solve, "oldring", "nodisplay");
1306    list real_sols = list();
1307    list tmpl;
1308    for(k=1; k<=size(SOL); k++) {
1309        if(find(string(SOL[k]),"I")==0 && find(string(SOL[k]),"i")==0) {
1310            tmpl = list();
1311            for(i=1; i<=size(SOL[k]); i++) {
1312                tmpl = tmpl + list(string(SOL[k][i]));
1313            }
1314            real_sols = real_sols + list(tmpl);
1315        }
1316    }
1317    return(real_sols);
1318}
1319example {
1320    "EXAMPLE:"; echo = 2;
1321    ring r = 0, (x,y), dp;
1322    number a = 2;
1323    number b = 3;
1324    ideal j = (x^2-a),(y^3-b);
1325    real_solve(j);
1326}
1327
1328proc rootminpoly(list #)
1329"
1330USAGE: rootminpoly(list #)
1331
1332RETURN: A root of the current minpoly
1333as a string representation of a complex number with
1334the given precision #[1] (default: 30).
1335E.g. ring r=(0,s),x,dp; minpoly = s^2-2; => rootminpoly() 1.41421356237309504880168872421
1336
1337ASSUME: The current minpoly is non-zero.
1338"
1339{
1340    int prec = 30;
1341    int k, done;
1342    if(size(#)>0) {
1343        prec = #[1];
1344    }
1345    short = 0;
1346    string str_lag = sprintf("list lag = laguerre_solve(%s);", minpoly);
1347    string str_ring = sprintf("ring r_sqrt = (complex,prec,I),(%s),lp;", parstr(basering));
1348    execute(str_ring);
1349    execute(str_lag);
1350//    lag;
1351    // choose a real solution, if it exists:
1352    done = 0;
1353    for(k=1; k<=size(lag) && done==0; k++) {
1354        if(find(string(lag[k]),"I")==0) {
1355            done = k;
1356        }
1357    }
1358    if(done==0) {
1359//        "no real solution.";
1360    }
1361
1362    if(size(lag)>2) {
1363        // return the first real solution
1364        return(sprintf("%s",lag[done]));
1365    }
1366
1367    if(sprintf("%s",lag[1])[1] == "-") {
1368        return(sprintf("%s",lag[2]));
1369    } else {
1370        if(sprintf("%s",lag[1])[1] == "(") {
1371            if(sprintf("%s",lag[1])[2] == "-") {
1372                return(sprintf("%s",lag[2]));
1373            } else {
1374                return(sprintf("%s",lag[1]));
1375            }
1376        } else {
1377            return(sprintf("%s",lag[1]));
1378        }
1379    }
1380    short = 1;
1381}
1382example
1383{
1384   "EXAMPLE:"; echo =2;
1385   ring r=(0,s),x,dp;
1386   minpoly = s^2-2;
1387   rootminpoly();
1388
1389   ring R=(0,s),x,dp;
1390   minpoly = s^2+2;
1391   rootminpoly();
1392}
1393
1394proc allroots_minpoly(list #)
1395"
1396USAGE: allroots_minpoly(list #)
1397
1398RETURN: a list of strings containing all real roots of the minimal polynomial of the active ring.
1399
1400ASSUME: The current minpoly is non-zero.
1401"
1402{
1403    int prec = 30;
1404    int k, done;
1405    if(size(#)>0) {
1406        prec = #[1];
1407    }
1408    short = 0;
1409    string str_lag = sprintf("list lag = laguerre_solve(%s);", minpoly);
1410    string str_ring = sprintf("ring r_sqrt = (complex,prec,I),(%s),lp;", parstr(basering));
1411    execute(str_ring);
1412    execute(str_lag);
1413
1414    // only take the real solutions:
1415    done = 0;
1416    list real_sols = list();
1417    for(k=1; k<=size(lag) && done==0; k++) {
1418        if(find(string(lag[k]),"I")==0) {
1419            real_sols = real_sols + list(string(lag[k]));
1420        }
1421    }
1422    return(real_sols);
1423}
1424example {
1425    "EXAMPLE:"; echo = 2;
1426   ring r=(0,s),x,dp;
1427   minpoly = s^3-2;
1428   allroots_minpoly();
1429
1430   ring R=(0,s),x,dp;
1431   minpoly = s^2-2;
1432   allroots_minpoly();
1433}
1434
1435proc decstr2ratstr(string str)
1436"
1437USAGE: decstr2ratstr(string str)
1438Convert a decimal number of not more than 30 digits to a rational number with 14 digits.
1439
1440REMARK: This procedure still has to be adapted to accept other precisions!
1441"
1442{
1443    ring decR = (complex,30,I),(x),lp;
1444    execute("number r="+str+";");
1445    execute("r = "+truncdec(r,14)+";");
1446    return(real2ratstr(r));
1447}
1448
1449proc real2ratstr(number r)
1450"
1451USAGE: real2ratstr(number r)
1452
1453RETURN: A string containing a rational number representing the decimal number r.
1454
1455ASSUME: The current ring has either real or complex base field.
1456"
1457{
1458    string ratstr = "number("+string(r*number(10000000000000000))+")/number(10000000000000000)";
1459    return(ratstr);
1460}
1461
1462proc truncdec(number r, int decs)
1463"
1464USAGE: truncdec(number r, int decs)
1465Truncates a decimal number r to the given number (decs) of digits.
1466
1467RETURN: A string representing the truncated number.
1468"
1469{
1470    string str = string(r);
1471    return(str[1,(decs+2)]);
1472}
1473
1474proc string_of_vars(ideal I)
1475"
1476USAGE: string_of_vars(ideal I)
1477
1478RETURN: A string of all variables contained in the ideal I, separated by commas.
1479"
1480{
1481    list listvars = list();
1482    intvec v;
1483    int i;
1484    poly p;
1485    for(i=size(I);i>0;i--)
1486    {
1487        p=I[i];
1488        while(p!=0)
1489        {
1490            v=v+leadexp(p);
1491            p=p-lead(p);
1492        }
1493    }
1494    for(i=1; i<=nvars(basering); i++) {
1495        if(v[i] > 0) {
1496            listvars = listvars + list(var(i));
1497        }
1498    }
1499    string strvars = string(listvars);
1500    return(strvars);
1501}
Note: See TracBrowser for help on using the repository browser.