This file is indexed.

/usr/share/yacas/scripts/texform.rep/code.ys is in yacas 1.3.6-2+b1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/* TeXForm: convert Yacas objects to TeX math mode strings */

/* version 0.4 */

/* Changelog
	0.1	basic functionality
	0.2 fixed bracketing of Exp, added all infix ops and math functions
	0.3 fixed bracketing of lists, changed bracketing of math functions, modified TeX representation of user-defined functions (up to two-letter functions are in italics), added TeX Greek letters
	0.4 added nth roots, Sum, Limit, Integrate, hyperbolics, set operations, Abs, Max, Min, "==", ":=", Infinity; support indexed expressions A[i] and matrices.
	0.4.1 bugfixes for [] operator, support for multiple indices a[1][2][3]
	0.4.2 fix for variable names ending on digits "a2" represented as $a_2$
	0.4.3 bugfixes: complex I, indeterminate integration; relaxed bracketing of Sin()-like functions; implemented $TeX$ and $LaTeX$ correctly now (using \textrm{})
	0.4.4 use ordinary instead of partial derivative if expression has only one variable
	0.4.5 fixes for bracketing of Sum(); added <> to render as \sim and <=> to render as \approx; added Bin()
	0.4.6 moved the <> and <=> operators to stdopers.ys
	0.4.7 added Factorize() i.e. Product()
	0.4.8 added D(x,n), Deriv(x,n), =>, and fixed errors with ArcSinh, ArcCosh, ArcTanh
	0.4.9 fixed omission: (fraction)^n was not put in brackets
	0.4.10 cosmetic change: insert \cdot between numbers in cases like 2*10^n
	0.4.11 added DumpErrors() to TexForm for the benefit of TeXmacs notebooks
	0.4.12 implement the % operation as Mod
	0.4.13 added Bessel{I,J,K,Y}, Ortho{H,P,T,U}, with a general framework for usual two-argument functions of the form $A_n(x)$; fix for Max, Min
	0.4.14 added mathematical notation for Floor(), Ceil()
	0.4.15 added Prog() represented by ( )
	0.4.16 added Zeta()
*/

/* To do:
	0. Find and fix bugs.
	1. The current bracketing approach has limitations: can't omit extra brackets sometimes. " sin a b" is ambiguous, so need to do either "sin a sin b" or "(sin a) b" Hold((a*b)*Sqrt(x)). The current approach is *not* to bracket functions unless the enveloping operation is more binding than multiplication. This produces "sin a b" for both Sin(a*b) and Sin(a)*b but this is the current mathematical practice.
	2. Need to figure out how to deal with variable names such as "alpha3"
*/

/// TeXmacs prettyprinter
TexForm(_expr) <-- [DumpErrors();WriteString(TeXForm(expr));NewLine();];

RuleBase("TeXForm",{expression});
RuleBase("TeXForm",{expression, precedence});

/* Boolean predicate */


/* this function will put TeX brackets around the string if predicate holds */

Function ("TeXFormBracketIf", {predicate, string})
[
	Check(IsBoolean(predicate) And IsString(string), "TeXForm internal error: non-boolean and/or non-string argument of TeXFormBracketIf");
	If(predicate, ConcatStrings("\\left( ", string, "\\right) "), string);
];

/* First, we convert TeXForm(x) to TeXForm(x, precedence). The enveloping precedence will determine whether we need to bracket the results. So TeXForm(x, TeXFormMaxPrec()) will always print "x", while TeXForm(x,-TeXFormMaxPrec()) will always print "(x)".
*/

TeXFormMaxPrec() := 60000;	 /* This precedence will never be bracketed. It is equal to KMaxPrec */

/// main front-end
100 # TeXForm(_x) <-- ConcatStrings("$", TeXForm(x, TeXFormMaxPrec()), "$");

/* Replace numbers and variables -- never bracketed except explicitly */

110 # TeXForm(x_IsNumber, _p) <-- String(x);
/* Variables */
200 # TeXForm(x_IsAtom, _p) <-- TeXFormTeXify(String(x));

/* Strings must be quoted but not bracketed */
100 # TeXForm(x_IsString, _p) <-- ConcatStrings("\\mathrm{", x, "}");

/* Listify(...) can generate lists with atoms that would otherwise result in unparsable expressions. */
100 # TeXForm(x_IsAtom, _p)_(IsInfix(String(x))) <-- ConcatStrings("\\mathrm{", String(x), "}");


/* Lists: make sure to have matrices processed before them. Enveloping precedence is irrelevant because lists are always bracketed. List items are never bracketed. Note that TeXFormFinishList({a,b}) generates ",a,b" */

100 # TeXForm(x_IsList, _p)_(Length(x)=0) <-- TeXFormBracketIf(True, "");
110 # TeXForm(x_IsList, _p) <-- TeXFormBracketIf(True, ConcatStrings(TeXForm(Head(x), TeXFormMaxPrec()), TeXFormFinishList(Tail(x)) ) );
100 # TeXFormFinishList(x_IsList)_(Length(x)=0) <-- "";
110 # TeXFormFinishList(x_IsList) <-- ConcatStrings(", ", TeXForm(Head(x), TeXFormMaxPrec()), TeXFormFinishList(Tail(x)));

/* Replace operations */


	/* Template for "regular" binary infix operators:
100 # TeXForm(_x + _y, _p) <-- TeXFormBracketIf(p<OpPrecedence("+"), ConcatStrings(TeXForm(x, OpLeftPrecedence("+")), " + ", TeXForm(y, OpRightPrecedence("+")) ) );
	*/
// special cases: things like x*2 and 2*10^x look ugly without a period
// cases like x*2
115 # TeXForm(_expr * n_IsNumber, _p) <-- TeXFormBracketIf(p<OpPrecedence("*"), ConcatStrings(TeXForm(expr, OpLeftPrecedence("*")), "\\cdot ", TeXForm(n, OpRightPrecedence("*")) ) );
// cases like a*20! and a*10^x
116 # TeXForm(_n * _expr, _p) _ (IsFunction(expr) And Contains({"^", "!", "!!"}, Type(expr)) And IsNumber(Listify(expr)[2])) <-- TeXFormBracketIf(p<OpPrecedence("*"), ConcatStrings(TeXForm(n, OpLeftPrecedence("*")), "\\cdot ", TeXForm(expr, OpRightPrecedence("*")) ) );

	/* generic binary ops here */
120 # TeXForm(expr_IsFunction, _p)_(NrArgs(expr)=2 And IsInfix(Type(expr)) ) <-- TeXFormBracketIf(p<OpPrecedence(Type(expr)), ConcatStrings(TeXForm(Listify(expr)[2], OpLeftPrecedence(Type(expr))), TeXFormTeXify(Type(expr)), TeXForm(Listify(expr)[3], OpRightPrecedence(Type(expr))) ) );

	/* Template for "regular" unary prefix operators:
100 # TeXForm(+ _y, _p) <-- TeXFormBracketIf(p<OpPrecedence("+"), ConcatStrings(" + ", TeXForm(y, OpRightPrecedence("+")) ) );
	Note that OpRightPrecedence needs to be defined for prefix ops or else we won't be able to tell combined prefix/infix ops like "-" from strictly prefix ops.
	*/

	/* generic unary ops here */
	/* prefix */
120 # TeXForm(expr_IsFunction, _p)_(NrArgs(expr)=1 And IsPrefix(Type(expr))) <-- TeXFormBracketIf(p<OpPrecedence(Type(expr)), ConcatStrings(
	TeXFormTeXify(Type(expr)),
	TeXForm(Listify(expr)[2], OpRightPrecedence(Type(expr)))
) );
	/* postfix */
120 # TeXForm(expr_IsFunction, _p)_(NrArgs(expr)=1 And IsPostfix(Type(expr))) <-- TeXFormBracketIf(p<OpLeftPrecedence(Type(expr)), ConcatStrings(
	TeXForm(Listify(expr)[2], OpLeftPrecedence(Type(expr))),
	TeXFormTeXify(Type(expr))
) );

	/* fraction and its operands are never bracketed except when they are under power */
100 # TeXForm(_x / _y, _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings("\\frac{", TeXForm(x, TeXFormMaxPrec()), "}{", TeXForm(y, TeXFormMaxPrec()), "} ") );

	/* power's argument is never bracketed but it must be put in braces. Chained powers must be bracketed. Powers of 1/n are displayed as roots. */
100 # TeXForm(_x ^ (1/2), _p) <-- ConcatStrings("\\sqrt{", TeXForm(x, TeXFormMaxPrec()), "}");
101 # TeXForm(_x ^ (1/_y), _p) <-- ConcatStrings("\\sqrt[", TeXForm(y, TeXFormMaxPrec()), "]{", TeXForm(x, TeXFormMaxPrec()), "}");


120 # TeXForm(_x ^ _y, _p) <-- TeXFormBracketIf(p<=OpPrecedence("^"), ConcatStrings(TeXForm(x, OpPrecedence("^")), " ^{", TeXForm(y, TeXFormMaxPrec()), "}" ) );

/* functions */


LocalSymbols(TeXFormRegularOps, TeXFormRegularPrefixOps, TeXFormGreekLetters, TeXFormSpecialNames) [

	/* addition, subtraction, multiplication, all comparison and logical operations are "regular" */

  TeXFormRegularOps :=
  {
    {"+"," + "},
    {"-"," - "},
    {"*"," "},
    {":=","\\equiv "},
    {"=="," = "},
    {"="," = "},
    {"!=","\\neq "},
    {"<=","\\leq "},
    {">=","\\geq "},
    {"<"," < "},
    {">"," > "},
    {"And","\\wedge "},
    {"Or", "\\vee "},
    {"<>", "\\sim "},
    {"<=>", "\\approx "},
    {"=>", "\\Rightarrow "},
    {"%", "\\bmod "},
  };

  TeXFormRegularPrefixOps := { {"+"," + "}, {"-"," - "}, {"Not"," \\neg "} };



    /* Unknown function: precedence 200. Leave as is, never bracket the function itself and bracket the argument(s) automatically since it's a list. Other functions are precedence 100 */

  TeXFormGreekLetters := {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega", "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega", "varpi", "varrho", "varsigma", "varphi", "varepsilon"};
  TeXFormSpecialNames := {
    {"I", "\\imath "},	// this prevents a real uppercase I, use BesselI instead
    {"Pi", "\\pi "},	// this makes it impossible to have an uppercase Pi... hopefully it's not needed
    {"Infinity", "\\infty "},
    {"TeX", "\\textrm{\\TeX\\/}"},
    {"LaTeX", "\\textrm{\\LaTeX\\/}"},
    {"Max", "\\max "},	// this replaces these function names
    {"Min", "\\min "},
    {"Prog", " "},
    {"Zeta", "\\zeta "},
  };


  /* this function will take a user-defined variable or function name and output either this name unmodified if it's only 2 characters long, or the name in normal text if it's longer, or a TeX Greek letter code */
  Function ("TeXFormTeXify", {string})
  [
    Check(IsString(string), "TeXForm internal error: non-string argument of TeXFormTeXify");
    /* Check if it's a greek letter or a special name */
    If (Contains(AssocIndices(TeXFormSpecialNames), string), TeXFormSpecialNames[string],
    If (Contains(TeXFormGreekLetters, string), ConcatStrings("\\", string, " "),
    If (Contains(AssocIndices(TeXFormRegularOps), string), TeXFormRegularOps[string],
    If (Contains(AssocIndices(TeXFormRegularPrefixOps), string), TeXFormRegularPrefixOps[string],
    If (Length(string) >= 2 And IsNumber(Atom(StringMid'Get(2, Length(string)-1, string))), ConcatStrings(StringMid'Get(1,1,string), "_{", StringMid'Get(2, Length(string)-1, string), "}"),
    If (Length(string) > 2, ConcatStrings("\\mathrm{ ", string, " }"),
    string
    ))))));
  ];

];

/* */

/* Unknown bodied function */

200 # TeXForm(x_IsFunction, _p) _ (IsBodied(Type(x))) <-- [
	Local(func, args, last'arg);
	func := Type(x);
	args := Tail(Listify(x));
	last'arg := PopBack(args);
	TeXFormBracketIf(p<OpPrecedence(func), ConcatStrings(
	  TeXFormTeXify(func), TeXForm(args, TeXFormMaxPrec()),  TeXForm(last'arg, OpPrecedence(func))
	));
];

/* Unknown infix function : already done above
210 # TeXForm(x_IsFunction, _p)_(IsInfix(Type(x))) <-- ConcatStrings(TeXFormTeXify(Type(x)), TeXForm(Tail(Listify(x)), TeXFormMaxPrec()) );
*/
/* Unknown function that is not prefix, infix or postfix */
220 # TeXForm(x_IsFunction, _p) <-- ConcatStrings(TeXFormTeXify(Type(x)), TeXForm(Tail(Listify(x)), TeXFormMaxPrec()) );

	/* Never bracket Sqrt or its arguments */
100 # TeXForm(Sqrt(_x), _p) <-- ConcatStrings("\\sqrt{", TeXForm(x, TeXFormMaxPrec()), "}");

	/* Always bracket Exp's arguments */
100 # TeXForm(Exp(_x), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings("\\exp ", TeXFormBracketIf(True, TeXForm(x, TeXFormMaxPrec())) ) );


LocalSymbols(TeXFormMathFunctions, TeXFormMathFunctions2) [

  /* Sin, Cos, etc. and their argument is bracketed when it's a sum or product but not bracketed when it's a power. */
  /// supported Yacas functions: "mathematical" functions of one argument which sometimes do not require parentheses (e.g. $\sin x$ )
  TeXFormMathFunctions := { {"Cos","\\cos "}, {"Sin","\\sin "}, {"Tan","\\tan "}, {"Cosh","\\cosh "}, {"Sinh","\\sinh "}, {"Tanh","\\tanh "}, {"Ln","\\ln "}, {"ArcCos","\\arccos "}, {"ArcSin","\\arcsin "}, {"ArcTan","\\arctan "}, {"ArcCosh","\\mathrm{arccosh}\\, "}, {"ArcSinh","\\mathrm{arcsinh}\\, "}, {"ArcTanh","\\mathrm{arctanh}\\, "},
  {"Erf", "\\mathrm{erf}\\, "}, {"Erfc", "\\mathrm{erfc}\\, "},
  };

  /// supported Yacas functions: functions of two arguments of the form $A_n(x)$
  TeXFormMathFunctions2 := {
  {"BesselI", "I "}, {"BesselJ", "J "},
  {"BesselK", "K "}, {"BesselY", "Y "},
  {"OrthoH", "H "}, {"OrthoP", "P "},
  {"OrthoT", "T "}, {"OrthoU", "U "},
  };

  // generic two-argument functions of the form $A(x,y)$ where just the name has to be changed: handle this using the usual naming conversion scheme (TeXFormSpecialNames)

  /* Precedence of 120 because we'd like to process other functions like sqrt or exp first */

  // generic math functions of one argument
  120 # TeXForm(expr_IsFunction, _p) _ (NrArgs(expr)=1 And Contains(AssocIndices(TeXFormMathFunctions), Type(expr)) ) <-- TeXFormBracketIf(p<OpPrecedence("*"), ConcatStrings(TeXFormMathFunctions[Type(expr)], TeXForm( Listify(expr)[2], OpPrecedence("*")) ) );

  /// math functions two arguments of the form $A_n(x)$
  120 # TeXForm(expr_IsFunction, _p) _ (NrArgs(expr)=2 And Contains(AssocIndices(TeXFormMathFunctions2), Type(expr)) ) <-- TeXFormBracketIf(p<OpPrecedence("*"),
    ConcatStrings(
    TeXFormMathFunctions2[Type(expr)],
    "_{",
    TeXForm( Listify(expr)[2], TeXFormMaxPrec()),	// never bracket the subscript
    "}",
    TeXFormBracketIf(True, TeXForm(Listify(expr)[3], TeXFormMaxPrec()) ) // always bracket the function argument
    )
  );

]; // LocalSymbols(TeXFormMathFunctions, TeXFormMathFunctions2)


/* Complex numbers */
100 # TeXForm(Complex(0, 1), _p) <-- TeXForm(Hold(I), p);
100 # TeXForm(Complex(_x, 0), _p) <-- TeXForm(x, p);
110 # TeXForm(Complex(_x, 1), _p) <-- TeXForm(x+Hold(I), p);
110 # TeXForm(Complex(0, _y), _p) <-- TeXForm(Hold(I)*y, p);
120 # TeXForm(Complex(_x, _y), _p) <-- TeXForm(x+Hold(I)*y, p);

/* Abs(), Floor(), Ceil() are displayed as special brackets */

100 # TeXForm(Abs(_x), _p) <-- ConcatStrings("\\left| ", TeXForm(x, TeXFormMaxPrec()), "\\right| ");
100 # TeXForm(Floor(_x), _p) <-- ConcatStrings("\\left\\lfloor ", TeXForm(x, TeXFormMaxPrec()), "\\right\\rfloor ");
100 # TeXForm(Ceil(_x), _p) <-- ConcatStrings("\\left\\lceil ", TeXForm(x, TeXFormMaxPrec()), "\\right\\rceil ");

/* Some functions which are displayed as infix: Mod, Union, Intersection, Difference, Contains */

100 # TeXForm(Mod(_x, _y), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(TeXForm(x, OpPrecedence("/")), "\\bmod ", TeXForm(y, OpPrecedence("/")) ) );

100 # TeXForm(Union(_x, _y), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(TeXForm(x, OpPrecedence("/")), "\\cup ", TeXForm(y, OpPrecedence("/")) ) );

100 # TeXForm(Intersection(_x, _y), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(TeXForm(x, OpPrecedence("/")), "\\cap ", TeXForm(y, OpPrecedence("/")) ) );

100 # TeXForm(Difference(_x, _y), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(TeXForm(x, OpPrecedence("/")), "\\setminus ", TeXForm(y, OpPrecedence("/")) ) );

/* "Contains" is displayed right to left */

100 # TeXForm(Contains(_x, _y), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(TeXForm(y, OpPrecedence("/")), "\\in ", TeXForm(x, OpPrecedence("/")) ) );

/// Binomial coefficients: always bracketed
100 # TeXForm(Bin(_n, _m), _p) <-- TeXFormBracketIf(False, ConcatStrings("{", TeXForm(n, TeXFormMaxPrec()), " \\choose ", TeXForm(m, TeXFormMaxPrec()), "}" )
);

/* Some functions with limits: Lim, Sum, Integrate */

100 # TeXForm(Sum(_x, _x1, _x2, _expr), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings("\\sum _{", TeXForm(x, TeXFormMaxPrec()), " = ", TeXForm(x1, TeXFormMaxPrec()), "} ^{", TeXForm(x2, TeXFormMaxPrec()), "} ", TeXForm(expr, OpPrecedence("*")) ) );

100 # TeXForm(Factorize(_x, _x1, _x2, _expr), _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings("\\prod _{", TeXForm(x, TeXFormMaxPrec()), " = ", TeXForm(x1, TeXFormMaxPrec()), "} ^{", TeXForm(x2, TeXFormMaxPrec()), "} ", TeXForm(expr, OpPrecedence("*")) ) );

100 # TeXForm(Integrate(_x, _x1, _x2) _expr, _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(
"\\int _{", TeXForm(x1, TeXFormMaxPrec()), "} ^{", TeXForm(x2, TeXFormMaxPrec()), " } ", TeXForm(expr, OpPrecedence("*")), " d", TeXForm(x, TeXFormMaxPrec())
) );

/* indeterminate integration */
100 # TeXForm(Integrate(_x) _expr, _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings(
"\\int ", TeXForm(expr, OpPrecedence("*")), " d", TeXForm(x, TeXFormMaxPrec())
) );

100 # TeXForm(Limit(_x, _x1) _expr, _p) <-- TeXFormBracketIf(p<OpPrecedence("/"), ConcatStrings("\\lim _{", TeXForm(x, TeXFormMaxPrec()), "\\rightarrow ", TeXForm(x1, TeXFormMaxPrec()), "} ", TeXForm(expr, OpPrecedence("/")) ) );

/* Derivatives */

/* Use partial derivative only when the expression has several variables */
100 # TeXForm(Deriv(_x)_y, _p) <-- TeXFormBracketIf(p<OpPrecedence("-"), ConcatStrings(
	If(Length(VarList(y))>1, "\\frac{\\partial}{\\partial ", "\\frac{d}{d "
	), TeXForm(x, OpPrecedence("^")), "}", TeXForm(y, OpPrecedence("/")) ) );

100 # TeXForm(Deriv(_x, _n)_y, _p) <-- TeXFormBracketIf(p<OpPrecedence("-"), ConcatStrings(
	If(
		Length(VarList(y))>1,
		"\\frac{\\partial^" : TeXForm(n, TeXFormMaxPrec()) : "}{\\partial ",
		"\\frac{d^" : TeXForm(n, TeXFormMaxPrec()) : "}{d "
	), TeXForm(x, OpPrecedence("^")), " ^", TeXForm(n, TeXFormMaxPrec()), "}", TeXForm(y, OpPrecedence("/")) ) );
100 # TeXForm(D(_x)_y, _p) <-- TeXForm(Deriv(x) y, p);
100 # TeXForm(D(_x, _n)_y, _p) <-- TeXForm(Deriv(x, n) y, p);

/* Indexed expressions */

/* This seems not to work because x[i] is replaced by Nth(x,i) */
/*
100 # TeXForm(_x [ _i ], _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}");
*/
/* Need to introduce auxiliary function, or else have trouble with arguments of Nth being lists */
100 # TeXForm(Nth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p);
100 # TeXForm(TeXFormNth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p);
110 # TeXForm(Nth(Nth(_x, _i), _j), _p) <-- TeXForm(TeXFormNth(x, List(i,j)), p);
120 # TeXForm(Nth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}");
120 # TeXForm(TeXFormNth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}");

/* Matrices are always bracketed. Precedence 80 because lists are at 100. */

80 # TeXForm(M_IsMatrix, _p) <-- TeXFormBracketIf(True, TeXFormPrintMatrix(M));

Function ("TeXFormPrintMatrix", {M})
[
/*
	Want something like "\begin{array}{cc} a & b \\ c & d \\ e & f \end{array}"
	here, "cc" is alignment and must be given for each column
*/
	Local(row, col, result, ncol);
	result := "\\begin{array}{";
	ForEach(col, M[1]) result:=ConcatStrings(result, "c");
	result := ConcatStrings(result, "}");

	ForEach(row, 1 .. Length(M)) [
		ForEach(col, 1 .. Length(M[row])) [
			result := ConcatStrings( result, " ", TeXForm(M[row][col], TeXFormMaxPrec()), If(col = Length(M[row]), If(row = Length(M), "", " \\\\"), " &"));
		];
	];

	ConcatStrings(result, " \\end{array} ");
];