string defaultformat(int n, string trailingzero="", bool fixed=false, bool signed=true) { return "$%"+trailingzero+"."+string(n)+(fixed ? "f" : "g")+"$"; } string defaultformat=defaultformat(4); string defaultseparator="\!\times\!"; string ask(string prompt) { write(stdout,prompt); return stdin; } string getstring(string name="", string default="", string prompt="", bool store=true) { string[] history=history(name,1); if(history.length > 0) default=history[0]; if(prompt == "") prompt=name+"? [%s] "; prompt=replace(prompt,new string[][] {{"%s",default}}); string s=readline(prompt,name); if(s == "") s=default; else saveline(name,s,store); return s; } int getint(string name="", int default=0, string prompt="", bool store=true) { return (int) getstring(name,(string) default,prompt,store); } real getreal(string name="", real default=0, string prompt="", bool store=true) { return (real) getstring(name,(string) default,prompt,store); } pair getpair(string name="", pair default=0, string prompt="", bool store=true) { return (pair) getstring(name,(string) default,prompt,store); } triple gettriple(string name="", triple default=(0,0,0), string prompt="", bool store=true) { return (triple) getstring(name,(string) default,prompt,store); } // returns a string with all occurrences of string 'before' in string 's' // changed to string 'after'. string replace(string s, string before, string after) { return replace(s,new string[][] {{before,after}}); } // Like texify but don't convert embedded TeX commands: \${} string TeXify(string s) { static string[][] t={{"&","\&"},{"%","\%"},{"_","\_"},{"#","\#"},{"<","$<$"}, {">","$>$"},{"|","$|$"},{"^","$\hat{\ }$"}, {"~","$\tilde{\ }$"},{" ","\phantom{ }"}}; return replace(s,t); } private string[][] trans1={{'\\',"\backslash "}, {"$","\$"},{"{","\{"},{"}","\}"}}; private string[][] trans2={{"\backslash ","$\backslash$"}}; // Convert string to TeX string texify(string s) { return TeXify(replace(replace(s,trans1),trans2)); } // Convert string to TeX, preserving newlines string verbatim(string s) { bool space=substr(s,0,1) == '\n'; static string[][] t={{'\n',"\\"}}; t.append(trans1); s=TeXify(replace(replace(s,t),trans2)); return space ? "\ "+s : s; } // Split a string into an array of substrings delimited by delimiter // If delimiter is an empty string, use space delimiter but discard empty // substrings. TODO: Move to C++ code. string[] split(string s, string delimiter="") { bool prune=false; if(delimiter == "") { prune=true; delimiter=" "; } string[] S; int last=0; int i; int N=length(delimiter); int n=length(s); while((i=find(s,delimiter,last)) >= 0) { if(i > last || (i == last && !prune)) S.push(substr(s,last,i-last)); last=i+N; } if(n > last || (n == last && !prune)) S.push(substr(s,last,n-last)); return S; } // Returns an array of strings obtained by splitting s into individual // characters. TODO: Move to C++ code. string[] array(string s) { int len=length(s); string[] S=new string[len]; for(int i=0; i < len; ++i) S[i]=substr(s,i,1); return S; } // Concatenate an array of strings into a single string. // TODO: Move to C++ code. string operator +(...string[] a) { string S; for(string s : a) S += s; return S; } int system(string s) { return system(split(s)); } int[] operator ecast(string[] a) { return sequence(new int(int i) {return (int) a[i];},a.length); } real[] operator ecast(string[] a) { return sequence(new real(int i) {return (real) a[i];},a.length); } // Read contents of file as a string. string file(string s) { file f=input(s); string s; while(!eof(f)) { s += f+'\n'; } return s; } string italic(string s) { return s != "" ? "{\it "+s+"}" : s; } string baseline(string s, string template="\strut") { return s != "" && settings.tex != "none" ? "\vphantom{"+template+"}"+s : s; } string math(string s) { return s != "" ? "$"+s+"$" : s; } private void notimplemented(string text) { abort(text+" is not implemented for the '"+settings.tex+"' TeX engine"); } string jobname(string name) { int pos=rfind(name,"-"); return pos >= 0 ? "\ASYprefix\jobname"+substr(name,pos) : name; } string graphic(string name, string options="") { if(latex()) { if(options != "") options="["+options+"]"; string includegraphics="\includegraphics"+options; return includegraphics+"{"+(settings.inlinetex ? jobname(name) : name)+"}"; } if(settings.tex != "context") notimplemented("graphic"); return "\externalfigure["+name+"]["+options+"]"; } string graphicscale(real x) { return string(settings.tex == "context" ? 1000*x : x); } string minipage(string s, real width=100bp) { if(latex()) return "\begin{minipage}{"+(string) (width/pt)+"pt}"+s+"\end{minipage}"; if(settings.tex != "context") notimplemented("minipage"); return "\startframedtext[none][frame=off,width="+(string) (width/pt)+ "pt]"+s+"\stopframedtext"; } void usepackage(string s, string options="") { if(!latex()) notimplemented("usepackage"); string usepackage="\usepackage"; if(options != "") usepackage += "["+options+"]"; texpreamble(usepackage+"{"+s+"}"); } void pause(string w="Hit enter to continue") { write(w); w=stdin; } string format(string format=defaultformat, bool forcemath=false, real x, string locale="") { return format(format,forcemath,defaultseparator,x,locale); } string phantom(string s) { return settings.tex != "none" ? "\phantom{"+s+"}" : ""; } string[] spinner=new string[] {'|','/','-','\\'}; spinner.cyclic=true; void progress(bool3 init=default) { static int count=-1; static int lastseconds=-1; if(init == true) { lastseconds=0; write(stdout,' ',flush); } else if(init == default) { int seconds=seconds(); if(seconds > lastseconds) { lastseconds=seconds; write(stdout,'\b'+spinner[++count],flush); } } else write(stdout,'\b',flush); } restricted int ocgindex=0;