1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 /* texprint.c for gretl - LaTeX output from modeling */
21
22 #include "libgretl.h"
23 #include "var.h"
24 #include "johansen.h"
25 #include "texprint.h"
26
27 #include <glib.h>
28
29 static char colspec[4][8];
30 static int use_custom;
31 static int use_pdf;
32
33 #define tex_screen_zero(x) ((fabs(x) > 1.0e-17)? x : 0.0)
34
tex_using_custom_tabular(void)35 int tex_using_custom_tabular (void)
36 {
37 return use_custom;
38 }
39
tex_column_format(int i)40 const char *tex_column_format (int i)
41 {
42 if (i >= 0 && i < 4) {
43 return colspec[i];
44 } else {
45 return "";
46 }
47 }
48
set_tex_use_pdf(const char * prog)49 void set_tex_use_pdf (const char *prog)
50 {
51 const char *p = strrslash(prog);
52 char test[4];
53
54 /* looking for "pdflatex", possibly preceded by
55 an absolute path */
56
57 p = (p == NULL)? prog : p + 1;
58
59 *test = '\0';
60 strncat(test, p, 3);
61 gretl_lower(test);
62 use_pdf = !strcmp(test, "pdf");
63 }
64
get_tex_use_pdf(void)65 int get_tex_use_pdf (void)
66 {
67 return use_pdf;
68 }
69
tex_greek_var(const char * s)70 static const char *tex_greek_var (const char *s)
71 {
72 if (!strcmp(s, "alpha")) {
73 return "\\alpha";
74 } else if (!strcmp(s, "beta")) {
75 return "\\beta";
76 } else if (!strcmp(s, "gamma")) {
77 return "\\gamma";
78 } else if (!strcmp(s, "delta")) {
79 return "\\delta";
80 } else if (!strcmp(s, "epsilon")) {
81 return "\\epsilon";
82 } else if (!strcmp(s, "chi")) {
83 return "\\chi";
84 } else if (!strcmp(s, "pi")) {
85 return "\\pi";
86 } else if (!strcmp(s, "phi")) {
87 return "\\phi";
88 } else if (!strcmp(s, "psi")) {
89 return "\\psi";
90 } else if (!strcmp(s, "lambda")) {
91 return "\\lambda";
92 }
93
94 return NULL;
95 }
96
97 /**
98 * tex_escape:
99 * @targ: target string (must be pre-allocated)
100 * @src: source string.
101 *
102 * Copies from @src to @targ, escaping any characters in @src that are
103 * special to TeX (by inserting a leading backslash).
104 *
105 * Returns: the transformed copy of the string
106 */
107
tex_escape(char * targ,const char * src)108 char *tex_escape (char *targ, const char *src)
109 {
110 char *p = targ;
111
112 if (src == NULL) {
113 fprintf(stderr, "tex_escape: src is NULL\n");
114 *p = '\0';
115 return p;
116 }
117
118 while (*src) {
119 if (*src == '$' || *src == '&' || *src == '_' ||
120 *src == '%' || *src == '#')
121 *targ++ = '\\';
122 *targ++ = *src++;
123 }
124
125 *targ = '\0';
126
127 return p;
128 }
129
130 /**
131 * tex_escape_new:
132 * @src: source string.
133 *
134 * Returns: a copy of @src in which any characters that require
135 * escaping are preceded by a backslash.
136 */
137
tex_escape_new(const char * src)138 char *tex_escape_new (const char *src)
139 {
140 const char *s = src;
141 char *ret = NULL;
142 int i, len = 0;
143
144 if (src == NULL) {
145 fprintf(stderr, "tex_escape: src is NULL\n");
146 return gretl_strdup("");
147 }
148
149 while (*s) {
150 if (*s == '$' || *s == '&' || *s == '_' ||
151 *s == '%' || *s == '#') {
152 len++;
153 }
154 len++;
155 }
156
157 ret = calloc(1, len + 1);
158 s = src;
159 i = 0;
160
161 while (*s) {
162 if (*s == '$' || *s == '&' || *s == '_' ||
163 *s == '%' || *s == '#') {
164 ret[i++] = '\\';
165 }
166 ret[i++] = *s;
167 }
168
169 return ret;
170 }
171
tex_math_pname(char * targ,const char * s)172 static int tex_math_pname (char *targ, const char *s)
173 {
174 char base[16], op[2], mod[8];
175 int n;
176
177 n = sscanf(s, "%15[^_^]%1[_^]%7s", base, op, mod);
178
179 if (n == 3 && (*mod == '{' || isdigit(*mod))) {
180 const char *tgreek = tex_greek_var(base);
181 const char *tbase = (tgreek != NULL)? tgreek : base;
182
183 if (*mod == '{') {
184 sprintf(targ, "$%s%s%s$", tbase, op, mod);
185 } else {
186 sprintf(targ, "$%s%s{%s}$", tbase, op, mod);
187 }
188 return 1;
189 }
190
191 return 0;
192 }
193
194 /**
195 * tex_escape_special:
196 * @targ: target string (must be pre-allocated)
197 * @src: source string.
198 *
199 * Copies from @src to @targ, escaping characters in @src that are
200 * special to TeX (by inserting a leading backslash). Unlike
201 * tex_escape(), this function does not mess with '$' in the
202 * source string, and it attempts to handle greek letters
203 * correctly.
204 *
205 * Returns: the transformed copy of the string.
206 */
207
tex_escape_special(char * targ,const char * src)208 char *tex_escape_special (char *targ, const char *src)
209 {
210 const char *tgreek;
211 char *p = targ;
212
213 if (strchr(src, '$')) {
214 /* don't mess with it */
215 strcpy(targ, src);
216 return targ;
217 }
218
219 tgreek = tex_greek_var(src);
220
221 if (tgreek != NULL) {
222 sprintf(targ, "$%s$", tgreek);
223 } else if (tex_math_pname(targ, src)) {
224 ; /* handled */
225 } else {
226 /* regular escape routine */
227 while (*src) {
228 if (*src == '&' || *src == '_' ||
229 *src == '%' || *src == '#') {
230 *p++ = '\\';
231 }
232 *p++ = *src++;
233 }
234
235 *p = '\0';
236 }
237
238 return targ;
239 }
240
241 /* Print the floating point number @x into the string @s, using the C
242 format "%*.f", with the digits following the decimal point given by
243 @dig. This is intended for use with the LaTeX tabular column
244 format "r@{.}l", so the decimal point is replaced by '&'. In
245 addition, it is presumed that we're _not_ in TeX math mode, so the
246 leading minus sign, if present, is "mathized" as "$-$".
247
248 NADBL is handled by printing a blank "r@{.}l" value.
249 */
250
tex_rl_float(double x,char * s,int dig)251 char *tex_rl_float (double x, char *s, int dig)
252 {
253 char *p;
254
255 if (na(x)) {
256 return strcpy(s, "\\multicolumn{2}{c}{}");
257 }
258
259 x = screen_zero(x);
260
261 if (x < 0) {
262 sprintf(s, "$-$%.*f", dig, -x);
263 } else {
264 sprintf(s, "%.*f", dig, x);
265 }
266
267 p = strchr(s, '.');
268
269 if (p == NULL) {
270 p = strchr(s, ',');
271 }
272
273 if (p != NULL) {
274 *p = '&';
275 } else {
276 strcat(s, "&");
277 }
278
279 return s;
280 }
281
282 /* When a floating point value is printed as TeX in the C format "%g",
283 process the exponent part. It is assumed we're not in TeX math
284 mode, so in a negative exponent such as "e-06" the minus will
285 appear as a hyphen, which does not look very good. Using a true
286 minus sign in the exponent doesn't look very good either (too
287 wide); we compromise by writing the minus as an en dash.
288 */
289
tex_modify_exponent(char * s)290 char *tex_modify_exponent (char *s)
291 {
292 char *p = strchr(s, 'e');
293
294 if (p != NULL) {
295 int minus = (*(p+1) == '-');
296 char tmp[16];
297
298 sprintf(tmp, "\\textrm{e%s%s}", (minus)? "--" : "+", p + 2);
299 strcpy(p, tmp);
300 }
301
302 return s;
303 }
304
tex_rl_double_dig(double x,char * s,int d)305 static char *tex_rl_double_dig (double x, char *s, int d)
306 {
307 char *p;
308
309 if (na(x)) {
310 return strcpy(s, "\\multicolumn{2}{c}{}");
311 }
312
313 x = screen_zero(x);
314
315 if (x < 0) {
316 sprintf(s, "$-$%#.*g", d, -x);
317 } else {
318 sprintf(s, "%#.*g", d, x);
319 }
320
321 if (strchr(s, 'e') != NULL) {
322 tex_modify_exponent(s);
323 }
324
325 p = strchr(s, '.');
326
327 if (p == NULL) {
328 p = strchr(s, ',');
329 }
330
331 if (p != NULL) {
332 *p = '&';
333 } else {
334 strcat(s, "&");
335 }
336
337 return s;
338 }
339
340 /* Print the floating point number @x into the string @s, using the C
341 format "%#*.g", with GRETL_DIGITS of precision. This is intended
342 for use with the LaTeX tabular column format "r@{.}l", so the
343 decimal point is replaced by '&'. In addition, it is presumed that
344 we're _not_ in TeX math mode, so the leading minus sign, if
345 present, is "mathized" as "$-$".
346
347 NADBL is handled by printing a blank "r@{.}l" value.
348 */
349
tex_rl_double(double x,char * s)350 char *tex_rl_double (double x, char *s)
351 {
352 return tex_rl_double_dig(x, s, get_gretl_digits());
353 }
354
355 /* Print the floating point number @x into the string @s, using the C
356 format "%#*.g", with @dig digits of precision. It is presumed
357 that we're _not_ in TeX math mode, so the leading minus sign, if
358 present, is "mathized" as "$-$".
359
360 NADBL is handled by printing a space.
361 */
362
tex_sprint_double_digits(double x,char * s,int dig)363 char *tex_sprint_double_digits (double x, char *s, int dig)
364 {
365 if (na(x)) {
366 return strcpy(s, " ");
367 }
368
369 x = screen_zero(x);
370
371 if (x < 0.0) {
372 sprintf(s, "$-$%#.*g", dig, -x);
373 } else {
374 sprintf(s, "%#.*g", dig, x);
375 }
376
377 if (strchr(s, 'e') != NULL) {
378 tex_modify_exponent(s);
379 }
380
381 return s;
382 }
383
384 /* Basically as above, but for use when in TeX math mode */
385
tex_sprint_math_double_digits(double x,char * s,int dig)386 static char *tex_sprint_math_double_digits (double x, char *s, int dig)
387 {
388 if (na(x)) {
389 return strcpy(s, "\\mbox{NA}");
390 }
391
392 x = screen_zero(x);
393
394 sprintf(s, "%#.*g", dig, x);
395
396 if (strchr(s, 'e') != NULL) {
397 tex_modify_exponent(s);
398 }
399
400 return s;
401 }
402
403 /* Print the floating point number @x into the string @s, using the C
404 format "%#*.g", with GRETL_DIGITS of precision. It is presumed
405 that we're _not_ in TeX math mode, so the leading minus sign, if
406 present, is "mathized" as "$-$".
407
408 NADBL is handled by printing a space.
409 */
410
tex_sprint_double(double x,char * s)411 char *tex_sprint_double (double x, char *s)
412 {
413 int d = get_gretl_digits();
414
415 if (na(x)) {
416 return strcpy(s, " ");
417 }
418
419 x = screen_zero(x);
420
421 if (x < 0.0) {
422 sprintf(s, "$-$%#.*g", d, -x);
423 } else {
424 sprintf(s, "%#.*g", d, x);
425 }
426
427 if (strchr(s, 'e') != NULL) {
428 tex_modify_exponent(s);
429 }
430
431 return s;
432 }
433
434 /* Print the floating point number @x directly to @prn, using the C
435 format "%#*.g", with GRETL_DIGITS of precision. It is presumed
436 that we're _not_ in TeX math mode, so the leading minus sign, if
437 present, is "mathized" as "$-$".
438
439 NADBL is handled by printing a space.
440 */
441
tex_print_double(double x,PRN * prn)442 void tex_print_double (double x, PRN *prn)
443 {
444 char s[32];
445
446 tex_sprint_double(x, s);
447 pputs(prn, s);
448 }
449
tex_make_cname(char * cname,const char * src)450 static void tex_make_cname (char *cname, const char *src)
451 {
452 char *p;
453 unsigned char c;
454
455 if (src == NULL || *src == '\0') return;
456
457 p = strrchr(src, '_');
458 if (p == NULL) {
459 tex_escape(cname, src);
460 return;
461 }
462
463 c = (unsigned char) *(p + 1);
464
465 if (isdigit(c)) {
466 int lag = atoi(++p);
467
468 sprintf(cname, "$u_{t-%d}^2$", lag);
469 } else {
470 tex_escape(cname, src);
471 }
472 }
473
tex_greek_param(char * targ,const char * src)474 static int tex_greek_param (char *targ, const char *src)
475 {
476 const char *tgreek = tex_greek_var(src);
477
478 if (tgreek != NULL) {
479 sprintf(targ, "$%s$", tgreek);
480 return 1;
481 } else {
482 *targ = '\0';
483 return 0;
484 }
485 }
486
tex_garch_coeff_name(char * targ,const char * src,int inmath)487 static void tex_garch_coeff_name (char *targ, const char *src,
488 int inmath)
489 {
490 char fmt[16], vname[VNAMELEN], vnesc[16];
491 int lag;
492
493 sprintf(fmt, "%%%d[^(](%%d)", VNAMELEN - 1);
494
495 if (sscanf(src, fmt, vname, &lag) == 2) {
496 /* e.g. "alpha(0)" */
497 if (!inmath) {
498 sprintf(targ, "$\\%s_{%d}$", vname, lag);
499 } else {
500 sprintf(targ, "\\%s_{%d}", vname, lag);
501 }
502 } else {
503 /* regular variable name */
504 tex_escape(vnesc, src);
505 if (inmath) {
506 sprintf(targ, "\\mbox{%s}", vnesc);
507 } else {
508 strcpy(targ, vnesc);
509 }
510 }
511 }
512
tex_mp_coeff_name(char * targ,const char * src,int inmath)513 static void tex_mp_coeff_name (char *targ, const char *src,
514 int inmath)
515 {
516 char fmt[12], vname[VNAMELEN], vnesc[24];
517 int power;
518
519 tex_escape(vnesc, src);
520
521 sprintf(fmt, "%%%d[^^]^%%d", VNAMELEN - 1);
522
523 if (sscanf(vnesc, fmt, vname, &power) == 2) {
524 /* variable raised to some power */
525 if (!inmath) {
526 sprintf(targ, "%s$^{%d}$", vname, power);
527 } else {
528 sprintf(targ, "\\mbox{%s}^%d", vname, power);
529 }
530 } else {
531 /* regular variable name */
532 if (inmath) {
533 sprintf(targ, "\\mbox{%s}", vnesc);
534 } else {
535 strcpy(targ, vnesc);
536 }
537 }
538 }
539
tex_arma_coeff_name(char * targ,const char * src,int inmath)540 static void tex_arma_coeff_name (char *targ, const char *src,
541 int inmath)
542 {
543 char vname[VNAMELEN], vnesc[32], texname[48];
544 int i;
545
546 if (sscanf(src, "phi_%d", &i)) {
547 if (!inmath) {
548 sprintf(targ, "$\\phi_{%d}$", i);
549 } else {
550 sprintf(targ, "\\phi_{%d}", i);
551 }
552 } else if (sscanf(src, "Phi_%d", &i)) {
553 if (!inmath) {
554 sprintf(targ, "$\\Phi_{%d}$", i);
555 } else {
556 sprintf(targ, "\\Phi_{%d}", i);
557 }
558 } else if (sscanf(src, "theta_%d", &i)) {
559 if (!inmath) {
560 sprintf(targ, "$\\theta_{%d}$", i);
561 } else {
562 sprintf(targ, "\\theta_{%d}", i);
563 }
564 } else if (sscanf(src, "Theta_%d", &i)) {
565 if (!inmath) {
566 sprintf(targ, "$\\Theta_{%d}$", i);
567 } else {
568 sprintf(targ, "\\Theta_{%d}", i);
569 }
570 } else if (strstr(src, "(-") != NULL) {
571 char fmt[16];
572
573 sprintf(fmt, "%%%d[^(](-%%d)", VNAMELEN - 1);
574
575 if (sscanf(src, fmt, vname, &i) == 2) {
576 if (!strcmp(vname, "y")) {
577 strcpy(texname, "y");
578 } else {
579 tex_escape(vnesc, vname);
580 if (!inmath) {
581 strcpy(texname, vnesc);
582 } else {
583 sprintf(texname, "\\mbox{%s}", vnesc);
584 }
585 }
586 if (!inmath) {
587 sprintf(targ, "%s$_{t-%d}$", texname, i);
588 } else {
589 sprintf(targ, "%s_{t-%d}", texname, i);
590 }
591 } else {
592 tex_escape(vnesc, src);
593 strcpy(targ, vnesc);
594 }
595 } else {
596 tex_escape(vnesc, src);
597 strcpy(targ, vnesc);
598 }
599 }
600
tex_VAR_varname(char * s,const MODEL * pmod,const DATASET * dset,int v)601 static void tex_VAR_varname (char *s, const MODEL *pmod,
602 const DATASET *dset, int v)
603 {
604 char tmp[32], base[12];
605 int lag;
606
607 gretl_model_get_param_name(pmod, dset, v, tmp);
608
609 if (sscanf(tmp, "%11[^_]_%d", base, &lag) == 2) {
610 sprintf(s, "%s$_{t-%d}$", base, lag);
611 } else {
612 tex_escape(s, tmp);
613 }
614 }
615
tex_VECM_varname(char * s,const MODEL * pmod,const DATASET * dset,int v)616 static void tex_VECM_varname (char *s, const MODEL *pmod,
617 const DATASET *dset, int v)
618 {
619 char tmp[32], base[12];
620 int lag;
621
622 gretl_model_get_param_name(pmod, dset, v, tmp);
623
624 if (sscanf(tmp, "d_%11[^_]_%d", base, &lag) == 2) {
625 sprintf(s, "$\\Delta$%s$_{t-%d}$", base, lag);
626 } else {
627 tex_escape(s, tmp);
628 }
629 }
630
tex_print_coeff_custom(const model_coeff * mc,PRN * prn)631 static int tex_print_coeff_custom (const model_coeff *mc, PRN *prn)
632 {
633 char fmt[12];
634
635 pprintf(prn, "%s & ", mc->name);
636
637 if (colspec[0][0]) {
638 /* coefficient */
639 if (na(mc->b)) {
640 pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
641 } else {
642 sprintf(fmt, "$%s$", colspec[0]);
643 pprintf(prn, fmt, mc->b);
644 }
645 }
646
647 if (!colspec[1][0] && !colspec[2][0] && !colspec[3][0]) {
648 pputs(prn, " \\\\\n");
649 return 0;
650 }
651
652 if (colspec[1][0]) {
653 if (colspec[0][0]) {
654 pputs(prn, " & ");
655 }
656 /* standard error */
657 if (na(mc->se)) {
658 pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
659 } else {
660 pprintf(prn, colspec[1], mc->se);
661 }
662 }
663
664 if (!colspec[2][0] && !colspec[3][0]) {
665 pputs(prn, " \\\\\n");
666 return 0;
667 }
668
669 if (colspec[2][0]) {
670 if (colspec[0][0] || colspec[1][0]) {
671 pputs(prn, " & ");
672 }
673 /* t-ratio */
674 if (na(mc->tval)) {
675 if (mc->show_tval) {
676 pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
677 } else {
678 pprintf(prn, "\\multicolumn{1}{c}{}");
679 }
680 } else {
681 sprintf(fmt, "$%s$", colspec[2]);
682 pprintf(prn, fmt, mc->tval);
683 }
684 }
685
686 if (colspec[3][0]) {
687 if (colspec[0][0] || colspec[1][0] || colspec[2][0]) {
688 pputs(prn, " & ");
689 }
690 /* p-value (or perhaps slope) */
691 if (mc->show_pval) {
692 if (na(mc->pval)) {
693 pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
694 } else {
695 pprintf(prn, colspec[3], mc->pval);
696 }
697 } else if (!na(mc->slope)) {
698 pprintf(prn, colspec[3], mc->slope);
699 } else {
700 pprintf(prn, "\\multicolumn{1}{c}{}");
701 }
702 }
703
704 pputs(prn, " \\\\\n");
705
706 return 0;
707 }
708
make_tex_coeff_name(const MODEL * pmod,const DATASET * dset,int i,char * name)709 void make_tex_coeff_name (const MODEL *pmod, const DATASET *dset, int i,
710 char *name)
711 {
712 char pname[VNAMELEN];
713
714 gretl_model_get_param_name(pmod, dset, i, pname);
715
716 if (pmod->aux == AUX_ARCH) {
717 tex_make_cname(name, pname);
718 } else if (pmod->ci == NLS) {
719 if (!tex_greek_param(name, pname)) {
720 tex_escape(name, pname);
721 }
722 } else if (pmod->ci == ARMA) {
723 tex_arma_coeff_name(name, pname, 0);
724 } else if (pmod->ci == GARCH) {
725 tex_garch_coeff_name(name, pname, 0);
726 } else if (pmod->ci == VAR) {
727 tex_VAR_varname(name, pmod, dset, i);
728 } else if (pmod->aux == AUX_VECM) {
729 tex_VECM_varname(name, pmod, dset, i);
730 } else if (pmod->ci == MPOLS) {
731 tex_mp_coeff_name(name, pname, 0);
732 } else {
733 tex_escape(name, pname);
734 }
735 }
736
tex_multi_double(double x,char * numstr)737 static char *tex_multi_double (double x, char *numstr)
738 {
739 char *p;
740
741 if (na(x)) {
742 strcpy(numstr, " ");
743 } else if (x < 0) {
744 sprintf(numstr, "$-$%.15E", -x);
745 } else {
746 sprintf(numstr, "%.15E", x);
747 }
748
749 if ((p = strstr(numstr, "E-")) != NULL) {
750 char tmp[8];
751
752 sprintf(tmp, "E--%s", p + 2);
753 strcpy(p, tmp);
754 }
755
756 return numstr;
757 }
758
tex_print_coeff(const model_coeff * mc,PRN * prn)759 void tex_print_coeff (const model_coeff *mc, PRN *prn)
760 {
761 char col1[64], col2[64], col3[64], col4[64];
762 int ncols = 4;
763
764 if (mc->multi) {
765 tex_multi_double(mc->b, col1);
766 tex_multi_double(mc->se, col2);
767 pprintf(prn, "%s & %s & %s \\\\\n", mc->name, col1, col2);
768 return;
769 }
770
771 if (use_custom) {
772 tex_print_coeff_custom(mc, prn);
773 return;
774 }
775
776 if (na(mc->b)) {
777 sprintf(col1, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
778 } else {
779 tex_rl_double(mc->b, col1);
780 }
781
782 if (!na(mc->lo) && !na(mc->hi)) {
783 tex_rl_double(mc->lo, col2);
784 tex_rl_double(mc->hi, col3);
785 ncols = 3;
786 } else {
787 if (na(mc->se)) {
788 sprintf(col2, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
789 } else {
790 tex_rl_double(mc->se, col2);
791 }
792
793 if (na(mc->tval)) {
794 if (mc->show_tval) {
795 sprintf(col3, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
796 } else {
797 strcpy(col3, "\\multicolumn{2}{c}{}");
798 }
799 } else {
800 /* note: was tex_rl_float(mc->tval, col3, 4) */
801 tex_rl_double_dig(mc->tval, col3, 4);
802 }
803 }
804
805 *col4 = '\0';
806
807 if (!mc->show_pval && na(mc->slope)) {
808 strcpy(col4, "\\multicolumn{2}{c}{}");
809 } else if (!na(mc->slope)) {
810 tex_rl_double(mc->slope, col4);
811 } else if (mc->show_pval) {
812 if (!na(mc->pval)) {
813 tex_rl_float(mc->pval, col4, 4);
814 }
815 }
816
817 pprintf(prn, "%s &\n"
818 " %s &\n"
819 " %s &\n",
820 mc->name,
821 col1,
822 col2);
823
824 if (ncols == 4) {
825 pprintf(prn,
826 " %s &\n"
827 " %s \\\\\n",
828 col3,
829 col4);
830 } else {
831 pprintf(prn,
832 " %s \\\\\n",
833 col3);
834 }
835 }
836
837 static int
tex_custom_coeff_table_start(const char ** cols,gretlopt opt,PRN * prn)838 tex_custom_coeff_table_start (const char **cols, gretlopt opt, PRN *prn)
839 {
840 int i, ncols = 0;
841
842 for (i=0; i<4; i++) {
843 if (colspec[i][0]) {
844 ncols++;
845 }
846 }
847
848 if (!(opt & OPT_U)) {
849 /* not a user-defined model */
850 pputs(prn, "\\vspace{1em}\n\n");
851 }
852
853 pputs(prn, "\\begin{tabular}{l");
854
855 for (i=0; i<ncols; i++) {
856 pputc(prn, 'r');
857 }
858
859 pputs(prn, "}\n");
860
861 pprintf(prn, "\\multicolumn{1}{c}{%s} &\n", _(cols[0]));
862
863 if (colspec[0][0]) {
864 pprintf(prn, "\\multicolumn{1}{c}{%s}", _(cols[1]));
865 }
866
867 if (!colspec[1][0] && !colspec[2][0] && !colspec[3][0]) {
868 pputs(prn, " \\\\\n");
869 return ncols;
870 }
871
872 if (colspec[1][0]) {
873 if (colspec[0][0]) {
874 pputs(prn, " &\n");
875 }
876 pprintf(prn, "\\multicolumn{1}{c}{%s}", _(cols[2]));
877 }
878
879 if (!colspec[2][0] && !colspec[3][0]) {
880 pputs(prn, " \\\\\n");
881 return ncols;
882 }
883
884 if (colspec[2][0]) {
885 if (colspec[0][0] || colspec[1][0]) {
886 pputs(prn, " &\n");
887 }
888 pprintf(prn, "\\multicolumn{1}{c}{%s}", _(cols[3]));
889 }
890
891 if (colspec[3][0]) {
892 if (colspec[0][0] || colspec[1][0] || colspec[2][0]) {
893 pputs(prn, " &\n");
894 }
895 pprintf(prn, "\\multicolumn{1}{c}{%s}", _(cols[4]));
896 }
897
898 pputs(prn, " \\\\\n");
899
900 return ncols;
901 }
902
903 /* returns the number of columns in the coeff table */
904
tex_coeff_table_start(const char ** cols,gretlopt opt,PRN * prn)905 int tex_coeff_table_start (const char **cols, gretlopt opt, PRN *prn)
906 {
907 char pt = get_local_decpoint();
908 int i, mcols, binary = (opt & OPT_B);
909 int ncols = 1;
910
911 if (use_custom) {
912 return tex_custom_coeff_table_start(cols, opt, prn);
913 }
914
915 if (!(opt & OPT_U)) {
916 /* not a user-defined model */
917 pputs(prn, "\\vspace{1em}\n\n");
918 }
919
920 pputs(prn, "\\begin{tabular}{l");
921
922 for (i=1; cols[i] != NULL; i++) {
923 if (opt & OPT_M) {
924 pputc(prn, 'r');
925 } else {
926 pprintf(prn, "r@{%c}l", pt);
927 }
928 ncols += 2;
929 }
930
931 pprintf(prn, "}\n%s &\n", _(cols[0]));
932
933 mcols = (opt & OPT_M)? 1 : 2;
934
935 for (i=1; cols[i] != NULL; i++) {
936 bufspace(i, prn);
937 pprintf(prn, "\\multicolumn{%d}{c}{%s%s} %s\n", mcols, _(cols[i]),
938 (cols[i+1] == NULL && binary)? "$^*$" : "",
939 (cols[i+1] == NULL)? "\\\\[1ex]" : "&");
940 }
941
942 return ncols;
943 }
944
tex_coeff_table_end(PRN * prn)945 void tex_coeff_table_end (PRN *prn)
946 {
947 pputs(prn, "\\end{tabular}\n\n");
948 }
949
tex_print_VECM_omega(GRETL_VAR * vecm,const DATASET * dset,PRN * prn)950 void tex_print_VECM_omega (GRETL_VAR *vecm, const DATASET *dset, PRN *prn)
951 {
952 char vname[48];
953 const int *list = vecm->ylist;
954 double x;
955 int i, j;
956
957 pprintf(prn, "%s\n\n", _("Cross-equation covariance matrix"));
958 pputs(prn, "\\vspace{1em}\n");
959
960 pputs(prn, "\\begin{tabular}{");
961 pputs(prn, "l");
962 for (i=0; i<vecm->neqns; i++) {
963 pputs(prn, "r");
964 }
965 pputs(prn, "}\n & ");
966
967 for (i=0; i<vecm->neqns; i++) {
968 tex_escape(vname, dset->varname[list[i+1]]);
969 pprintf(prn, "$\\Delta$%s ", vname);
970 if (i == vecm->neqns - 1) {
971 pputs(prn, "\\\\\n");
972 } else {
973 pputs(prn, "& ");
974 }
975 }
976 pputc(prn, '\n');
977
978 for (i=0; i<vecm->neqns; i++) {
979 tex_escape(vname, dset->varname[list[i+1]]);
980 pprintf(prn, "$\\Delta$%s & ", vname);
981 for (j=0; j<vecm->neqns; j++) {
982 x = gretl_matrix_get(vecm->S, i, j);
983 tex_print_double(x, prn);
984 if (j == vecm->neqns - 1) {
985 pputs(prn, "\\\\\n");
986 } else {
987 pputs(prn, " & ");
988 }
989 }
990 }
991
992 pputs(prn, "\\end{tabular}\n\n");
993 pputs(prn, "\\vspace{1em}\n");
994
995 pputs(prn, "\\noindent\n");
996 pprintf(prn, "%s = ", _("determinant"));
997 tex_print_double(exp(vecm->ldet), prn);
998 pputs(prn, "\\\\\n");
999 }
1000
tex_beta_vname(char * s,const GRETL_VAR * v,const DATASET * dset,int i,PRN * prn)1001 static void tex_beta_vname (char *s,
1002 const GRETL_VAR *v,
1003 const DATASET *dset,
1004 int i, PRN *prn)
1005 {
1006 if (i < v->neqns) {
1007 tex_escape(s, dset->varname[v->ylist[i+1]]);
1008 pprintf(prn, "%s$_{t-1}$ & ", s);
1009 } else if (auto_restr(v) && i == v->neqns) {
1010 pprintf(prn, "%s & ", (jcode(v) == J_REST_CONST)? "const" : "trend");
1011 } else if (v->rlist != NULL) {
1012 int k = i - v->ylist[0] - auto_restr(v) + 1;
1013
1014 tex_escape(s, dset->varname[v->rlist[k]]);
1015 pprintf(prn, "%s$_{t-1}$ & ", s);
1016 }
1017 }
1018
tex_print_VECM_coint_eqns(GRETL_VAR * vecm,const DATASET * dset,PRN * prn)1019 void tex_print_VECM_coint_eqns (GRETL_VAR *vecm, const DATASET *dset, PRN *prn)
1020 {
1021 char s[32];
1022 JohansenInfo *jv = vecm->jinfo;
1023 int rows = gretl_matrix_rows(jv->Beta);
1024 int i, j;
1025 double x;
1026
1027 pputs(prn, "\\noindent\n");
1028 pputs(prn, _("Cointegrating vectors"));
1029 if (jv->Bse != NULL) {
1030 pprintf(prn, " (%s)\n", _("standard errors in parentheses"));
1031 } else {
1032 pputc(prn, '\n');
1033 }
1034
1035 pputs(prn, "\n\\vspace{1em}\n");
1036
1037 pputs(prn, "\\begin{tabular}{");
1038 pputs(prn, "l");
1039 for (i=0; i<jv->rank; i++) {
1040 pputs(prn, "r");
1041 }
1042 pputs(prn, "}\n");
1043
1044 for (i=0; i<rows; i++) {
1045 tex_beta_vname(s, vecm, dset, i, prn);
1046
1047 /* coefficients */
1048 for (j=0; j<jv->rank; j++) {
1049 x = gretl_matrix_get(jv->Beta, i, j);
1050 if (jv->Bse == NULL) {
1051 x /= gretl_matrix_get(jv->Beta, j, j);
1052 }
1053 tex_print_double(x, prn);
1054 if (j == jv->rank - 1) {
1055 pputs(prn, "\\\\\n");
1056 } else {
1057 pputs(prn, "& ");
1058 }
1059 }
1060
1061 if (jv->Bse != NULL) {
1062 /* standard errors */
1063 pputs(prn, " & ");
1064 for (j=0; j<jv->rank; j++) {
1065 x = gretl_matrix_get(jv->Bse, i, j);
1066 pputc(prn, '(');
1067 tex_print_double(x, prn);
1068 pputc(prn, ')');
1069 if (j == jv->rank - 1) {
1070 pputs(prn, "\\\\\n");
1071 } else {
1072 pputs(prn, "& ");
1073 }
1074 }
1075 }
1076 }
1077
1078 pputs(prn, "\\end{tabular}\n\n\\vspace{1em}\n");
1079 pputc(prn, '\n');
1080
1081 rows = gretl_matrix_rows(jv->Alpha);
1082
1083 pputs(prn, "\\noindent\n");
1084 pprintf(prn, _("Adjustment vectors"));
1085 if (jv->Ase != NULL) {
1086 pprintf(prn, " (%s)\n", _("standard errors in parentheses"));
1087 } else {
1088 pputc(prn, '\n');
1089 }
1090
1091 pputs(prn, "\n\\vspace{1em}\n");
1092
1093 pputs(prn, "\\begin{tabular}{");
1094 pputs(prn, "l");
1095 for (i=0; i<jv->rank; i++) {
1096 pputs(prn, "r");
1097 }
1098 pputs(prn, "}\n");
1099
1100 for (i=0; i<rows; i++) {
1101 tex_beta_vname(s, vecm, dset, i, prn);
1102
1103 /* coefficients */
1104 for (j=0; j<jv->rank; j++) {
1105 x = gretl_matrix_get(jv->Alpha, i, j);
1106 if (jv->Ase == NULL) {
1107 x /= gretl_matrix_get(jv->Alpha, j, j);
1108 }
1109 tex_print_double(x, prn);
1110 if (j == jv->rank - 1) {
1111 pputs(prn, "\\\\\n");
1112 } else {
1113 pputs(prn, "& ");
1114 }
1115 }
1116
1117 if (jv->Ase != NULL) {
1118 /* standard errors */
1119 pputs(prn, " & ");
1120 for (j=0; j<jv->rank; j++) {
1121 x = gretl_matrix_get(jv->Ase, i, j);
1122 pputc(prn, '(');
1123 tex_print_double(x, prn);
1124 pputc(prn, ')');
1125 if (j == jv->rank - 1) {
1126 pputs(prn, "\\\\\n");
1127 } else {
1128 pputs(prn, "& ");
1129 }
1130 }
1131 }
1132 }
1133
1134 pputs(prn, "\\end{tabular}\n\n\\vspace{1em}\n");
1135 pputc(prn, '\n');
1136
1137 }
1138
tex_print_VAR_ll_stats(GRETL_VAR * var,PRN * prn)1139 void tex_print_VAR_ll_stats (GRETL_VAR *var, PRN *prn)
1140 {
1141 pprintf(prn, "\\noindent\n%s = ", _("Log-likelihood"));
1142 tex_print_double(var->ll, prn);
1143 pputs(prn, "\\par\n");
1144
1145 pprintf(prn, "\\noindent\n%s = ", _("Determinant of covariance matrix"));
1146 tex_print_double(exp(var->ldet), prn);
1147 pputs(prn, "\\par\n");
1148
1149 pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("AIC"), var->AIC);
1150 pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("BIC"), var->BIC);
1151 pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("HQC"), var->HQC);
1152 }
1153
make_tex_prn(const char * fname,int eqn,int doc,int * err)1154 static PRN *make_tex_prn (const char *fname,
1155 int eqn, int doc,
1156 int *err)
1157 {
1158 PrnFormat fmt = GRETL_FORMAT_TEX;
1159 PRN *prn;
1160
1161 gretl_maybe_switch_dir(fname);
1162 prn = gretl_print_new_with_filename(fname, err);
1163
1164 if (prn != NULL) {
1165 if (eqn) {
1166 fmt |= GRETL_FORMAT_EQN;
1167 }
1168 if (doc) {
1169 fmt |= GRETL_FORMAT_DOC;
1170 }
1171 gretl_print_set_format(prn, fmt);
1172 }
1173
1174 return prn;
1175 }
1176
1177 /* mechanism for customizing gretl's tex preamble */
1178
1179 static char tex_preamble_file[MAXLEN];
1180
set_tex_locale_filename(char * local)1181 static const char *set_tex_locale_filename (char *local)
1182 {
1183 char *lang = getenv("LANG");
1184
1185 *local = '\0';
1186
1187 if (lang != NULL) {
1188 char lstr[3] = {0};
1189
1190 strncat(lstr, lang, 2);
1191 sprintf(local, "gretlpre_%s.tex", lstr);
1192 }
1193
1194 return local;
1195 }
1196
find_gretlpre(const char * path,const char * localname)1197 static int find_gretlpre (const char *path, const char *localname)
1198 {
1199 char test[MAXLEN];
1200 int err, gotit = 0;
1201
1202 if (*localname != '\0') {
1203 /* localized preamble file? */
1204 sprintf(test, "%s%s", path, localname);
1205 err = gretl_test_fopen(test, "r");
1206 if (!err) {
1207 strcpy(tex_preamble_file, test);
1208 gotit = 1;
1209 }
1210 }
1211
1212 if (!gotit) {
1213 /* regular preamble file? */
1214 sprintf(test, "%sgretlpre.tex", path);
1215 err = gretl_test_fopen(test, "r");
1216 if (!err) {
1217 strcpy(tex_preamble_file, test);
1218 gotit = 1;
1219 }
1220 }
1221
1222 return gotit;
1223 }
1224
set_gretl_tex_preamble(void)1225 void set_gretl_tex_preamble (void)
1226 {
1227 const char *path = gretl_workdir();
1228 char localname[16];
1229 int gotit;
1230
1231 set_tex_locale_filename(localname);
1232 gotit = find_gretlpre(path, localname);
1233
1234 if (!gotit) {
1235 path = maybe_get_default_workdir();
1236 if (path != NULL) {
1237 gotit = find_gretlpre(path, localname);
1238 }
1239 }
1240
1241 if (!gotit) {
1242 #ifdef OS_OSX
1243 path = gretl_app_support_dir();
1244 #else
1245 path = gretl_dotdir();
1246 #endif
1247 gotit = find_gretlpre(path, localname);
1248 }
1249
1250 gretl_error_clear();
1251 }
1252
landscape_modify_line(char * line)1253 static void landscape_modify_line (char *line)
1254 {
1255 char *p, *rem;
1256
1257 if (strstr(line, "landscape")) {
1258 return;
1259 }
1260
1261 p = strstr(line, "documentclass");
1262
1263 if (p != NULL) {
1264 if (*(p + 13) == '[') {
1265 p = strchr(p, ']');
1266 if (p != NULL) {
1267 rem = gretl_strdup(p);
1268 if (rem != NULL) {
1269 sprintf(p, ",landscape%s", rem);
1270 free(rem);
1271 }
1272 }
1273 } else {
1274 p += 13;
1275 rem = gretl_strdup(p);
1276 if (rem != NULL) {
1277 sprintf(p, "[landscape]%s", rem);
1278 free(rem);
1279 }
1280 }
1281 }
1282 }
1283
gretl_tex_preamble(PRN * prn,int fmt)1284 void gretl_tex_preamble (PRN *prn, int fmt)
1285 {
1286 char *lang = getenv("LANG");
1287 FILE *fp = NULL;
1288 int userfile = 0;
1289
1290 if (*tex_preamble_file != '\0') {
1291 fp = gretl_fopen(tex_preamble_file, "r");
1292 if (fp != NULL) {
1293 char line[256];
1294
1295 /* FIXME model table: longtable and geom packages */
1296
1297 while (fgets(line, sizeof line, fp)) {
1298 if (strstr(line, "documentclass") &&
1299 (fmt & GRETL_FORMAT_LANDSCAPE)) {
1300 landscape_modify_line(line);
1301 }
1302 pputs(prn, line);
1303 }
1304 userfile = 1;
1305 fclose(fp);
1306 fprintf(stderr, "gretltex: using preamble file\n %s\n",
1307 tex_preamble_file);
1308 }
1309 }
1310
1311 if (!userfile) {
1312 const char *paper = in_usa()? "letterpaper" : "a4paper";
1313 const char *driver = use_pdf ? "pdftex" : "dvips";
1314 const char *margin = "";
1315
1316 if (fmt & GRETL_FORMAT_MODELTAB) {
1317 margin = "margin=2cm,";
1318 }
1319
1320 pputs(prn, "\\documentclass");
1321
1322 if (fmt & GRETL_FORMAT_MODELTAB) {
1323 if (fmt & GRETL_FORMAT_LANDSCAPE) {
1324 pputs(prn, "[landscape]");
1325 }
1326 } else if (fmt & GRETL_FORMAT_LANDSCAPE) {
1327 pputs(prn, "[11pt,landscape]");
1328 } else {
1329 pputs(prn, "[11pt]");
1330 }
1331
1332 pputs(prn, "{article}\n");
1333
1334 #ifdef ENABLE_NLS
1335 pputs(prn, "\\usepackage[utf8]{inputenc}\n");
1336 #endif
1337
1338 if (lang != NULL && !strncmp(lang, "ru", 2)) {
1339 pputs(prn, "\\usepackage[russian]{babel}\n");
1340 }
1341
1342 pprintf(prn, "\\usepackage[%s,%s%s]{geometry}\n", paper, margin,
1343 driver);
1344
1345 if (fmt & GRETL_FORMAT_EQN) {
1346 pputs(prn, "\\usepackage{amsmath}\n");
1347 } else {
1348 pputs(prn, "\\usepackage{longtable}\n");
1349 }
1350
1351 pputs(prn, "\n\\begin{document}\n\n"
1352 "\\thispagestyle{empty}\n\n");
1353 }
1354 }
1355
1356 /* For use when printing a model in equation style: print the value
1357 unsigned, since the sign will be handled separately.
1358 */
1359
tex_print_unsigned_double(double x,PRN * prn)1360 static void tex_print_unsigned_double (double x, PRN *prn)
1361 {
1362 tex_print_double(fabs(x), prn);
1363 }
1364
1365 #define MAXCOEFF 4
1366
1367 /**
1368 * tex_print_equation:
1369 * @pmod: pointer to gretl MODEL struct.
1370 * @dset: information regarding the data set.
1371 * @opt: can include %OPT_S for a standalone document, and
1372 * %OPT_T to print t-ratios rather than standard errors.
1373 * @prn: gretl printing struct.
1374 *
1375 * Prints to @prn a gretl model in the form of a LaTeX equation, either as
1376 * a stand-alone document or as a fragment of LaTeX source for
1377 * insertion into a document.
1378 *
1379 * Returns: 0 on successful completion.
1380 */
1381
tex_print_equation(const MODEL * pmod,const DATASET * dset,gretlopt opt,PRN * prn)1382 int tex_print_equation (const MODEL *pmod, const DATASET *dset,
1383 gretlopt opt, PRN *prn)
1384 {
1385 double x;
1386 char tmp[48], vname[32];
1387 int i, nc = pmod->ncoeff;
1388 int split = 0, offvar = 0;
1389 int cchars = 0, ccount = 0;
1390 int se_digits;
1391 int sderr_ok = 1;
1392
1393 if (pmod->ci == HECKIT) {
1394 return E_NOTIMP;
1395 }
1396
1397 if (COUNT_MODEL(pmod->ci)) {
1398 offvar = gretl_model_get_int(pmod, "offset_var");
1399 if (offvar > 0) {
1400 nc++;
1401 }
1402 }
1403
1404 split = (nc > MAXCOEFF);
1405
1406 if (opt & OPT_S) {
1407 gretl_tex_preamble(prn, GRETL_FORMAT_EQN);
1408 } else{
1409 pputs(prn, "%%% the following needs the amsmath LaTeX package\n\n");
1410 }
1411
1412 /* initial setup */
1413 pputs(prn, "\\begin{gather}\n");
1414 if (split) {
1415 pputs(prn, "\\begin{split}\n");
1416 }
1417
1418 /* dependent variable */
1419 *tmp = '\0';
1420 if (pmod->depvar != NULL) {
1421 tex_escape(tmp, pmod->depvar);
1422 } else {
1423 i = gretl_model_get_depvar(pmod);
1424 tex_escape(tmp, dset->varname[i]);
1425 }
1426
1427 if (0 /* FIXME should this apply for DPANEL? (was ARBOND-specific) */) {
1428 pprintf(prn, "\\widehat{\\Delta \\rm %s} %s= \n", tmp, (split? "&" : ""));
1429 } else {
1430 pprintf(prn, "\\widehat{\\rm %s} %s= \n", tmp, (split? "&" : ""));
1431 }
1432
1433 if (pmod->ci == GARCH) {
1434 nc -= (1 + pmod->list[1] + pmod->list[2]);
1435 } else if (pmod->ci == PANEL) {
1436 nc = pmod->list[0] - 1;
1437 }
1438
1439 se_digits = get_gretl_digits();
1440 se_digits = se_digits > 5 ? 5 : se_digits;
1441
1442 /* coefficients times indep vars */
1443 for (i=0; i<nc; i++) {
1444 if (offvar > 0 && i == nc - 1) {
1445 pputc(prn, '+');
1446 tex_print_double(1.0, prn);
1447 } else {
1448 if (na(pmod->sderr[i])) {
1449 sderr_ok = 0;
1450 pprintf(prn, "%s{", (pmod->coeff[i] < 0.0)? "-" :
1451 (i > 0)? "+" : "");
1452 } else if (sderr_ok) {
1453 if (opt & OPT_T) {
1454 /* t-ratios */
1455 x = pmod->coeff[i] / pmod->sderr[i];
1456 pprintf(prn, "%s\\underset{(%.3f)}{",
1457 (pmod->coeff[i] < 0.0)? "-" :
1458 (i > 0)? "+" : "", x);
1459 } else {
1460 /* standard errors */
1461 tex_sprint_math_double_digits(pmod->sderr[i], tmp, se_digits);
1462 pprintf(prn, "%s\\underset{(%s)}{",
1463 (pmod->coeff[i] < 0.0)? "-" :
1464 (i > 0)? "+" : "", tmp);
1465 }
1466 }
1467 tex_print_unsigned_double(pmod->coeff[i], prn);
1468 pputc(prn, '}');
1469 }
1470
1471 if (i > 0 || pmod->ifc == 0) {
1472 /* regular coefficient, not const */
1473 if (offvar > 0 && i == nc - 1) {
1474 strcpy(vname, dset->varname[offvar]);
1475 } else {
1476 gretl_model_get_param_name(pmod, dset, i, vname);
1477 }
1478 cchars += strlen(vname);
1479
1480 pputs(prn, "\\,");
1481
1482 if (pmod->ci == ARMA) {
1483 tex_arma_coeff_name(tmp, vname, 1);
1484 pputs(prn, tmp);
1485 } else if (pmod->ci == GARCH) {
1486 tex_garch_coeff_name(tmp, vname, 1);
1487 pputs(prn, tmp);
1488 } else if (pmod->ci == MPOLS) {
1489 tex_mp_coeff_name(tmp, vname, 1);
1490 pputs(prn, tmp);
1491 } else {
1492 tex_escape(tmp, vname);
1493 pprintf(prn, "\\mbox{%s}", tmp);
1494 }
1495 }
1496 ccount++;
1497 if (split && (cchars > 30 || ccount > 3)) {
1498 pputs(prn, "\\\\\n& ");
1499 cchars = ccount = 0;
1500 } else {
1501 pputc(prn, '\n');
1502 }
1503 }
1504
1505 if (split) {
1506 pputs(prn, "\\end{split}\n");
1507 }
1508
1509 pputs(prn, " \\notag \\\\\n");
1510
1511 if (pmod->ci == GARCH) {
1512 int q = pmod->list[1];
1513 int p = pmod->list[2];
1514 int r = pmod->list[0] - 4;
1515
1516 if (opt & OPT_T) {
1517 x = pmod->coeff[r] / pmod->sderr[r];
1518 pprintf(prn, "\\hat{\\sigma}^2_t = \\underset{(%.3f)}{%g} ",
1519 x, pmod->coeff[r]);
1520 } else {
1521 tex_sprint_math_double_digits(pmod->sderr[r], tmp, se_digits);
1522 pprintf(prn, "\\hat{\\sigma}^2_t = \\underset{(%s)}{%g} ", /* FIXME? */
1523 tmp, pmod->coeff[r]);
1524 }
1525
1526 for (i=1; i<=q; i++) {
1527 if (opt & OPT_T) {
1528 x = pmod->coeff[r+i] / pmod->sderr[r+i];
1529 pprintf(prn, "%s\\underset{(%.3f)}{",
1530 (pmod->coeff[r+i] < 0.0)? "-" : "+", x);
1531 } else {
1532 tex_sprint_math_double_digits(pmod->sderr[r+i], tmp, se_digits);
1533 pprintf(prn, "%s\\underset{(%s)}{",
1534 (pmod->coeff[r+i] < 0.0)? "-" : "+", tmp);
1535 }
1536 tex_print_unsigned_double(pmod->coeff[r+i], prn);
1537 pputs(prn, "}\\,");
1538 pprintf(prn, "\\varepsilon^2_{t-%d}", i);
1539 }
1540
1541 for (i=1; i<=p; i++) {
1542 if (opt & OPT_T) {
1543 x = pmod->coeff[q+r+i] / pmod->sderr[q+r+i];
1544 pprintf(prn, "%s\\underset{(%.3f)}{",
1545 (pmod->coeff[q+r+i] < 0.0)? "-" : "+", x);
1546 } else {
1547 tex_sprint_math_double_digits(pmod->sderr[q+r+i], tmp, se_digits);
1548 pprintf(prn, "%s\\underset{(%s)}{",
1549 (pmod->coeff[q+r+i] < 0.0)? "-" : "+", tmp);
1550 }
1551 tex_print_unsigned_double(pmod->coeff[q+r+i], prn);
1552 pputs(prn, "}\\,");
1553 pprintf(prn, "\\sigma^2_{t-%d}", i);
1554 }
1555
1556 pputs(prn, "\\notag \\\\\n");
1557 }
1558
1559 pprintf(prn, "T = %d ", pmod->nobs);
1560
1561 /* additional info (R^2 etc) */
1562 if (pmod->ci == LAD) {
1563 x = gretl_model_get_double(pmod, "ladsum");
1564 if (!na(x)) {
1565 tex_sprint_math_double_digits(x, tmp, 5);
1566 pprintf(prn, "\\quad \\sum |\\hat{u}_t| = %s ", tmp);
1567 }
1568 } else {
1569 if (!na(pmod->adjrsq)) {
1570 pprintf(prn, "\\quad \\bar{R}^2 = %.4f ", pmod->adjrsq);
1571 } else if (!na(pmod->lnL)) {
1572 pprintf(prn, "\\quad \\mbox{ln}L = %.4f ", pmod->lnL);
1573 }
1574
1575 if (pmod->ci != LOGIT && pmod->ci != PROBIT && !na(pmod->fstt)) {
1576 tex_sprint_math_double_digits(pmod->fstt, tmp, 5);
1577 pprintf(prn, "\\quad F(%d,%d) = %s ",
1578 pmod->dfn, pmod->dfd, tmp);
1579 }
1580
1581 if (!na(pmod->sigma)) {
1582 tex_sprint_math_double_digits(pmod->sigma, tmp, 5);
1583 pprintf(prn, "\\quad \\hat{\\sigma} = %s ", tmp);
1584 }
1585
1586 if (!na(gretl_model_get_double(pmod, "rho_gls"))) {
1587 x = gretl_model_get_double(pmod, "rho_gls");
1588 tex_sprint_math_double_digits(x, tmp, 5);
1589 pprintf(prn, " \\quad \\rho = %s", tmp);
1590 }
1591 }
1592
1593 pputs(prn, "\\notag \\\\\n");
1594
1595 if (sderr_ok) {
1596 pprintf(prn, "\\centerline{(%s)} \\notag\n",
1597 (opt & OPT_T)? _("$t$-statistics in parentheses") :
1598 _("standard errors in parentheses"));
1599 } else {
1600 pputs(prn, "\\notag\n");
1601 }
1602
1603 pputs(prn, "\\end{gather}\n");
1604
1605 if (opt & OPT_S) {
1606 pputs(prn, "\n\\end{document}\n");
1607 }
1608
1609 return 0;
1610 }
1611
1612 /**
1613 * tex_print_model:
1614 * @pmod: pointer to gretl MODEL struct.
1615 * @dset: information regarding the data set.
1616 * @opt: may include %OPT_T in case of printing a model
1617 * in equation format, to use t-ratios instead of standard
1618 * errors.
1619 * @prn: gretl printing struct.
1620 *
1621 * Prints to @prn a gretl model in the form of either a LaTeX
1622 * table or an equation, and either as a stand-alone document or
1623 * as a fragment of LaTeX source for insertion into a document.
1624 *
1625 * The options are read from the format field of @prn --
1626 * gretl_print_set_format().
1627 *
1628 * Returns: 0 on successful completion.
1629 */
1630
tex_print_model(MODEL * pmod,const DATASET * dset,gretlopt opt,PRN * prn)1631 int tex_print_model (MODEL *pmod, const DATASET *dset,
1632 gretlopt opt, PRN *prn)
1633 {
1634 int err = 0;
1635
1636 if (RQ_SPECIAL_MODEL(pmod)) {
1637 return E_NOTIMP;
1638 }
1639
1640 if (tex_doc_format(prn)) {
1641 opt |= OPT_S;
1642 }
1643
1644 if (tex_eqn_format(prn)) {
1645 err = tex_print_equation(pmod, dset, opt, prn);
1646 } else {
1647 if (opt & OPT_T) {
1648 /* --format option */
1649 const char *s = get_optval_string(TABPRINT, OPT_T);
1650
1651 err = set_tex_param_format(s);
1652 }
1653 if (!err) {
1654 err = printmodel(pmod, dset, OPT_NONE, prn);
1655 }
1656 }
1657
1658 return err;
1659 }
1660
1661 /**
1662 * texprint:
1663 * @pmod: pointer to model.
1664 * @dset: information regarding the data set.
1665 * @fname: name of file to save.
1666 * @opt: if opt & %OPT_O, complete doc, else fragment;
1667 * if opt & %OPT_E print as equation, otherwise use tabular
1668 * format; if opt & %OPT_T show t-ratios rather than standard
1669 * errors when printing in equation format.
1670 *
1671 * Prints to file a gretl model in the form of a LaTeX table or
1672 * equation, either as a stand-alone document or as a fragment
1673 * of LaTeX source for insertion into a document.
1674 *
1675 * Returns: 0 on successful completion, 1 on error.
1676 */
1677
texprint(MODEL * pmod,const DATASET * dset,const char * fname,gretlopt opt)1678 int texprint (MODEL *pmod, const DATASET *dset,
1679 const char *fname, gretlopt opt)
1680 {
1681 PRN *prn;
1682 int eqn = (opt & OPT_E);
1683 int doc = (opt & OPT_O);
1684 int err = 0;
1685
1686 if (RQ_SPECIAL_MODEL(pmod)) {
1687 return E_NOTIMP;
1688 }
1689
1690 prn = make_tex_prn(fname, eqn, doc, &err);
1691
1692 if (!err) {
1693 err = tex_print_model(pmod, dset, opt, prn);
1694 gretl_print_destroy(prn);
1695 }
1696
1697 return err;
1698 }
1699
out_crlf(const char * buf,FILE * fp)1700 static void out_crlf (const char *buf, FILE *fp)
1701 {
1702 const char *p = buf;
1703
1704 #ifdef G_OS_WIN32
1705 /* fputs on Windows should take care of CR, LF */
1706 fputs(p, fp);
1707 #else
1708 while (*p) {
1709 if (*p == '\n') {
1710 fputs("\r\n", fp);
1711 } else {
1712 fputc(*p, fp);
1713 }
1714 p++;
1715 }
1716 #endif
1717 }
1718
rtfprint(MODEL * pmod,const DATASET * dset,const char * fname,gretlopt opt)1719 int rtfprint (MODEL *pmod, const DATASET *dset,
1720 const char *fname, gretlopt opt)
1721 {
1722 const char *buf = NULL;
1723 char *trbuf = NULL;
1724 PRN *prn;
1725 int err = 0;
1726
1727 if (RQ_SPECIAL_MODEL(pmod)) {
1728 return E_NOTIMP;
1729 }
1730
1731 prn = gretl_print_new(GRETL_PRINT_BUFFER, &err);
1732
1733 if (!err) {
1734 /* print the model to buffer first */
1735 gretl_print_set_format(prn, GRETL_FORMAT_RTF);
1736 err = printmodel(pmod, dset, opt, prn);
1737 }
1738
1739 if (!err) {
1740 /* recode if necessary */
1741 buf = gretl_print_get_buffer(prn);
1742 if (!gretl_is_ascii(buf)) {
1743 trbuf = utf8_to_rtf(buf);
1744 if (trbuf == NULL) {
1745 err = E_ALLOC;
1746 }
1747 }
1748 }
1749
1750 if (!err) {
1751 /* now send to file, converting LF to CR + LF
1752 as we go, if required
1753 */
1754 FILE *fp;
1755
1756 gretl_maybe_switch_dir(fname);
1757 fp = gretl_fopen(fname, "w");
1758
1759 if (fp == NULL) {
1760 err = E_FOPEN;
1761 } else if (trbuf != NULL) {
1762 out_crlf(trbuf, fp);
1763 } else {
1764 out_crlf(buf, fp);
1765 }
1766
1767 if (fp != NULL) {
1768 fclose(fp);
1769 }
1770 }
1771
1772 if (trbuf != NULL) {
1773 free(trbuf);
1774 }
1775
1776 if (prn != NULL) {
1777 gretl_print_destroy(prn);
1778 }
1779
1780 return err;
1781 }
1782
out_native(const char * buf,FILE * fp)1783 static void out_native (const char *buf, FILE *fp)
1784 {
1785 #ifdef G_OS_WIN32
1786 if (!gretl_is_ascii(buf)) {
1787 /* Windows: if the text is UTF-8, prepend
1788 the UTF-8 BOM */
1789 fputc(0xEF, fp);
1790 fputc(0xBB, fp);
1791 fputc(0xBF, fp);
1792 }
1793 #endif
1794 fputs(buf, fp);
1795 }
1796
csvprint(MODEL * pmod,const DATASET * dset,const char * fname,gretlopt opt)1797 int csvprint (MODEL *pmod, const DATASET *dset,
1798 const char *fname, gretlopt opt)
1799 {
1800 PRN *prn;
1801 int err = 0;
1802
1803 if (RQ_SPECIAL_MODEL(pmod)) {
1804 return E_NOTIMP;
1805 }
1806
1807 prn = gretl_print_new(GRETL_PRINT_BUFFER, &err);
1808
1809 if (!err) {
1810 /* print to buffer first */
1811 gretl_print_set_format(prn, GRETL_FORMAT_CSV);
1812 err = printmodel(pmod, dset, opt, prn);
1813 }
1814
1815 if (!err) {
1816 /* then send to file */
1817 const char *buf = gretl_print_get_buffer(prn);
1818 FILE *fp;
1819
1820 gretl_maybe_switch_dir(fname);
1821 fp = gretl_fopen(fname, "w");
1822
1823 if (fp == NULL) {
1824 err = E_FOPEN;
1825 } else {
1826 out_native(buf, fp);
1827 }
1828
1829 if (fp != NULL) {
1830 fclose(fp);
1831 }
1832 }
1833
1834 if (prn != NULL) {
1835 gretl_print_destroy(prn);
1836 }
1837
1838 return err;
1839 }
1840
1841 /**
1842 * tex_print_obs_marker:
1843 * @t: observation number.
1844 * @dset: data information struct.
1845 * @prn: gretl printing struct.
1846 *
1847 * Print a string (label, date or obs number) representing the given @t.
1848 */
1849
tex_print_obs_marker(int t,const DATASET * dset,PRN * prn)1850 void tex_print_obs_marker (int t, const DATASET *dset, PRN *prn)
1851 {
1852 if (dset->markers) {
1853 pprintf(prn, "\\texttt{%s} ", dset->S[t]);
1854 } else {
1855 char tmp[OBSLEN];
1856
1857 ntolabel(tmp, t, dset);
1858 pprintf(prn, "%8s ", tmp);
1859 }
1860 }
1861
check_colspec(const char * s)1862 static int check_colspec (const char *s)
1863 {
1864 const char *ok = "eEfgG";
1865 int w = 0, p = 0;
1866 char c = 0;
1867 int err = 1;
1868
1869 /* blank is OK */
1870 if (*s == '\0') {
1871 return 0;
1872 }
1873
1874 if (*s != '%') {
1875 return 1;
1876 }
1877
1878 s++;
1879
1880 if (*s == '#') { /* OK */
1881 s++;
1882 }
1883
1884 if (sscanf(s, "%d.%d%c", &w, &p, &c) == 3) {
1885 if (w != 0 && p > 0 && strchr(ok, c)) {
1886 err = 0;
1887 }
1888 } else if (sscanf(s, "%d%c", &w, &c) == 2) {
1889 if (w != 0 && strchr(ok, c)) {
1890 err = 0;
1891 }
1892 } else if (sscanf(s, ".%d%c", &p, &c) == 2) {
1893 if (p > 0 && strchr(ok, c)) {
1894 err = 0;
1895 }
1896 } else if (sscanf(s, "%c", &c) == 1) {
1897 if (strchr(ok, c)) {
1898 err = 0;
1899 }
1900 }
1901
1902 return err;
1903 }
1904
1905 /**
1906 * set_tex_param_format:
1907 * @s: stylized format string.
1908 *
1909 * Sets the format with which parameters will be printed, when
1910 * producing TeX tabular output.
1911 *
1912 * Returns: 0 on success, non-zero code on error.
1913 */
1914
set_tex_param_format(const char * s)1915 int set_tex_param_format (const char *s)
1916 {
1917 const char *p = s;
1918 int i, n = 0;
1919 int err = 0;
1920
1921 if (s == NULL || !strcmp(s, "default")) {
1922 use_custom = 0;
1923 return 0;
1924 }
1925
1926 for (i=0; i<4; i++) {
1927 colspec[i][0] = '\0';
1928 }
1929
1930 i = 0;
1931
1932 while (i < 4) {
1933 if (*s == '|' || *s == '\0') {
1934 if (n > 7) {
1935 n = 7;
1936 }
1937 strncat(colspec[i], p, n);
1938 #if 0
1939 fprintf(stderr, "spec %d = '%s'\n", i, colspec[i]);
1940 #endif
1941 err = check_colspec(colspec[i]);
1942 if (err || *s == '\0') {
1943 break;
1944 }
1945 p = s + 1;
1946 i++;
1947 n = 0;
1948 } else {
1949 n++;
1950 }
1951 s++;
1952 }
1953
1954 if (!err) {
1955 /* all columns can't be blank */
1956 n = 0;
1957 for (i=0; i<4; i++) {
1958 if (colspec[i][0] != '\0') n++;
1959 }
1960 if (n == 0) {
1961 err = E_ARGS;
1962 }
1963 }
1964
1965 if (err) {
1966 for (i=0; i<4; i++) {
1967 colspec[i][0] = '\0';
1968 }
1969 use_custom = 0;
1970 } else {
1971 use_custom = 1;
1972 }
1973
1974 return err;
1975 }
1976