/*
* gretl -- Gnu Regression, Econometrics and Time-series Library
* Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/* texprint.c for gretl - LaTeX output from modeling */
#include "libgretl.h"
#include "var.h"
#include "johansen.h"
#include "texprint.h"
#include
static char colspec[4][8];
static int use_custom;
static int use_pdf;
#define tex_screen_zero(x) ((fabs(x) > 1.0e-17)? x : 0.0)
int tex_using_custom_tabular (void)
{
return use_custom;
}
const char *tex_column_format (int i)
{
if (i >= 0 && i < 4) {
return colspec[i];
} else {
return "";
}
}
void set_tex_use_pdf (const char *prog)
{
const char *p = strrslash(prog);
char test[4];
/* looking for "pdflatex", possibly preceded by
an absolute path */
p = (p == NULL)? prog : p + 1;
*test = '\0';
strncat(test, p, 3);
gretl_lower(test);
use_pdf = !strcmp(test, "pdf");
}
int get_tex_use_pdf (void)
{
return use_pdf;
}
static const char *tex_greek_var (const char *s)
{
if (!strcmp(s, "alpha")) {
return "\\alpha";
} else if (!strcmp(s, "beta")) {
return "\\beta";
} else if (!strcmp(s, "gamma")) {
return "\\gamma";
} else if (!strcmp(s, "delta")) {
return "\\delta";
} else if (!strcmp(s, "epsilon")) {
return "\\epsilon";
} else if (!strcmp(s, "chi")) {
return "\\chi";
} else if (!strcmp(s, "pi")) {
return "\\pi";
} else if (!strcmp(s, "phi")) {
return "\\phi";
} else if (!strcmp(s, "psi")) {
return "\\psi";
} else if (!strcmp(s, "lambda")) {
return "\\lambda";
}
return NULL;
}
/**
* tex_escape:
* @targ: target string (must be pre-allocated)
* @src: source string.
*
* Copies from @src to @targ, escaping any characters in @src that are
* special to TeX (by inserting a leading backslash).
*
* Returns: the transformed copy of the string
*/
char *tex_escape (char *targ, const char *src)
{
char *p = targ;
if (src == NULL) {
fprintf(stderr, "tex_escape: src is NULL\n");
*p = '\0';
return p;
}
while (*src) {
if (*src == '$' || *src == '&' || *src == '_' ||
*src == '%' || *src == '#')
*targ++ = '\\';
*targ++ = *src++;
}
*targ = '\0';
return p;
}
/**
* tex_escape_new:
* @src: source string.
*
* Returns: a copy of @src in which any characters that require
* escaping are preceded by a backslash.
*/
char *tex_escape_new (const char *src)
{
const char *s = src;
char *ret = NULL;
int i, len = 0;
if (src == NULL) {
fprintf(stderr, "tex_escape: src is NULL\n");
return gretl_strdup("");
}
while (*s) {
if (*s == '$' || *s == '&' || *s == '_' ||
*s == '%' || *s == '#') {
len++;
}
len++;
}
ret = calloc(1, len + 1);
s = src;
i = 0;
while (*s) {
if (*s == '$' || *s == '&' || *s == '_' ||
*s == '%' || *s == '#') {
ret[i++] = '\\';
}
ret[i++] = *s;
}
return ret;
}
static int tex_math_pname (char *targ, const char *s)
{
char base[16], op[2], mod[8];
int n;
n = sscanf(s, "%15[^_^]%1[_^]%7s", base, op, mod);
if (n == 3 && (*mod == '{' || isdigit(*mod))) {
const char *tgreek = tex_greek_var(base);
const char *tbase = (tgreek != NULL)? tgreek : base;
if (*mod == '{') {
sprintf(targ, "$%s%s%s$", tbase, op, mod);
} else {
sprintf(targ, "$%s%s{%s}$", tbase, op, mod);
}
return 1;
}
return 0;
}
/**
* tex_escape_special:
* @targ: target string (must be pre-allocated)
* @src: source string.
*
* Copies from @src to @targ, escaping characters in @src that are
* special to TeX (by inserting a leading backslash). Unlike
* tex_escape(), this function does not mess with '$' in the
* source string, and it attempts to handle greek letters
* correctly.
*
* Returns: the transformed copy of the string.
*/
char *tex_escape_special (char *targ, const char *src)
{
const char *tgreek;
char *p = targ;
if (strchr(src, '$')) {
/* don't mess with it */
strcpy(targ, src);
return targ;
}
tgreek = tex_greek_var(src);
if (tgreek != NULL) {
sprintf(targ, "$%s$", tgreek);
} else if (tex_math_pname(targ, src)) {
; /* handled */
} else {
/* regular escape routine */
while (*src) {
if (*src == '&' || *src == '_' ||
*src == '%' || *src == '#') {
*p++ = '\\';
}
*p++ = *src++;
}
*p = '\0';
}
return targ;
}
/* Print the floating point number @x into the string @s, using the C
format "%*.f", with the digits following the decimal point given by
@dig. This is intended for use with the LaTeX tabular column
format "r@{.}l", so the decimal point is replaced by '&'. In
addition, it is presumed that we're _not_ in TeX math mode, so the
leading minus sign, if present, is "mathized" as "$-$".
NADBL is handled by printing a blank "r@{.}l" value.
*/
char *tex_rl_float (double x, char *s, int dig)
{
char *p;
if (na(x)) {
return strcpy(s, "\\multicolumn{2}{c}{}");
}
x = screen_zero(x);
if (x < 0) {
sprintf(s, "$-$%.*f", dig, -x);
} else {
sprintf(s, "%.*f", dig, x);
}
p = strchr(s, '.');
if (p == NULL) {
p = strchr(s, ',');
}
if (p != NULL) {
*p = '&';
} else {
strcat(s, "&");
}
return s;
}
/* When a floating point value is printed as TeX in the C format "%g",
process the exponent part. It is assumed we're not in TeX math
mode, so in a negative exponent such as "e-06" the minus will
appear as a hyphen, which does not look very good. Using a true
minus sign in the exponent doesn't look very good either (too
wide); we compromise by writing the minus as an en dash.
*/
char *tex_modify_exponent (char *s)
{
char *p = strchr(s, 'e');
if (p != NULL) {
int minus = (*(p+1) == '-');
char tmp[16];
sprintf(tmp, "\\textrm{e%s%s}", (minus)? "--" : "+", p + 2);
strcpy(p, tmp);
}
return s;
}
static char *tex_rl_double_dig (double x, char *s, int d)
{
char *p;
if (na(x)) {
return strcpy(s, "\\multicolumn{2}{c}{}");
}
x = screen_zero(x);
if (x < 0) {
sprintf(s, "$-$%#.*g", d, -x);
} else {
sprintf(s, "%#.*g", d, x);
}
if (strchr(s, 'e') != NULL) {
tex_modify_exponent(s);
}
p = strchr(s, '.');
if (p == NULL) {
p = strchr(s, ',');
}
if (p != NULL) {
*p = '&';
} else {
strcat(s, "&");
}
return s;
}
/* Print the floating point number @x into the string @s, using the C
format "%#*.g", with GRETL_DIGITS of precision. This is intended
for use with the LaTeX tabular column format "r@{.}l", so the
decimal point is replaced by '&'. In addition, it is presumed that
we're _not_ in TeX math mode, so the leading minus sign, if
present, is "mathized" as "$-$".
NADBL is handled by printing a blank "r@{.}l" value.
*/
char *tex_rl_double (double x, char *s)
{
return tex_rl_double_dig(x, s, get_gretl_digits());
}
/* Print the floating point number @x into the string @s, using the C
format "%#*.g", with @dig digits of precision. It is presumed
that we're _not_ in TeX math mode, so the leading minus sign, if
present, is "mathized" as "$-$".
NADBL is handled by printing a space.
*/
char *tex_sprint_double_digits (double x, char *s, int dig)
{
if (na(x)) {
return strcpy(s, " ");
}
x = screen_zero(x);
if (x < 0.0) {
sprintf(s, "$-$%#.*g", dig, -x);
} else {
sprintf(s, "%#.*g", dig, x);
}
if (strchr(s, 'e') != NULL) {
tex_modify_exponent(s);
}
return s;
}
/* Basically as above, but for use when in TeX math mode */
static char *tex_sprint_math_double_digits (double x, char *s, int dig)
{
if (na(x)) {
return strcpy(s, "\\mbox{NA}");
}
x = screen_zero(x);
sprintf(s, "%#.*g", dig, x);
if (strchr(s, 'e') != NULL) {
tex_modify_exponent(s);
}
return s;
}
/* Print the floating point number @x into the string @s, using the C
format "%#*.g", with GRETL_DIGITS of precision. It is presumed
that we're _not_ in TeX math mode, so the leading minus sign, if
present, is "mathized" as "$-$".
NADBL is handled by printing a space.
*/
char *tex_sprint_double (double x, char *s)
{
int d = get_gretl_digits();
if (na(x)) {
return strcpy(s, " ");
}
x = screen_zero(x);
if (x < 0.0) {
sprintf(s, "$-$%#.*g", d, -x);
} else {
sprintf(s, "%#.*g", d, x);
}
if (strchr(s, 'e') != NULL) {
tex_modify_exponent(s);
}
return s;
}
/* Print the floating point number @x directly to @prn, using the C
format "%#*.g", with GRETL_DIGITS of precision. It is presumed
that we're _not_ in TeX math mode, so the leading minus sign, if
present, is "mathized" as "$-$".
NADBL is handled by printing a space.
*/
void tex_print_double (double x, PRN *prn)
{
char s[32];
tex_sprint_double(x, s);
pputs(prn, s);
}
static void tex_make_cname (char *cname, const char *src)
{
char *p;
unsigned char c;
if (src == NULL || *src == '\0') return;
p = strrchr(src, '_');
if (p == NULL) {
tex_escape(cname, src);
return;
}
c = (unsigned char) *(p + 1);
if (isdigit(c)) {
int lag = atoi(++p);
sprintf(cname, "$u_{t-%d}^2$", lag);
} else {
tex_escape(cname, src);
}
}
static int tex_greek_param (char *targ, const char *src)
{
const char *tgreek = tex_greek_var(src);
if (tgreek != NULL) {
sprintf(targ, "$%s$", tgreek);
return 1;
} else {
*targ = '\0';
return 0;
}
}
static void tex_garch_coeff_name (char *targ, const char *src,
int inmath)
{
char fmt[16], vname[VNAMELEN], vnesc[16];
int lag;
sprintf(fmt, "%%%d[^(](%%d)", VNAMELEN - 1);
if (sscanf(src, fmt, vname, &lag) == 2) {
/* e.g. "alpha(0)" */
if (!inmath) {
sprintf(targ, "$\\%s_{%d}$", vname, lag);
} else {
sprintf(targ, "\\%s_{%d}", vname, lag);
}
} else {
/* regular variable name */
tex_escape(vnesc, src);
if (inmath) {
sprintf(targ, "\\mbox{%s}", vnesc);
} else {
strcpy(targ, vnesc);
}
}
}
static void tex_mp_coeff_name (char *targ, const char *src,
int inmath)
{
char fmt[12], vname[VNAMELEN], vnesc[24];
int power;
tex_escape(vnesc, src);
sprintf(fmt, "%%%d[^^]^%%d", VNAMELEN - 1);
if (sscanf(vnesc, fmt, vname, &power) == 2) {
/* variable raised to some power */
if (!inmath) {
sprintf(targ, "%s$^{%d}$", vname, power);
} else {
sprintf(targ, "\\mbox{%s}^%d", vname, power);
}
} else {
/* regular variable name */
if (inmath) {
sprintf(targ, "\\mbox{%s}", vnesc);
} else {
strcpy(targ, vnesc);
}
}
}
static void tex_arma_coeff_name (char *targ, const char *src,
int inmath)
{
char vname[VNAMELEN], vnesc[32], texname[48];
int i;
if (sscanf(src, "phi_%d", &i)) {
if (!inmath) {
sprintf(targ, "$\\phi_{%d}$", i);
} else {
sprintf(targ, "\\phi_{%d}", i);
}
} else if (sscanf(src, "Phi_%d", &i)) {
if (!inmath) {
sprintf(targ, "$\\Phi_{%d}$", i);
} else {
sprintf(targ, "\\Phi_{%d}", i);
}
} else if (sscanf(src, "theta_%d", &i)) {
if (!inmath) {
sprintf(targ, "$\\theta_{%d}$", i);
} else {
sprintf(targ, "\\theta_{%d}", i);
}
} else if (sscanf(src, "Theta_%d", &i)) {
if (!inmath) {
sprintf(targ, "$\\Theta_{%d}$", i);
} else {
sprintf(targ, "\\Theta_{%d}", i);
}
} else if (strstr(src, "(-") != NULL) {
char fmt[16];
sprintf(fmt, "%%%d[^(](-%%d)", VNAMELEN - 1);
if (sscanf(src, fmt, vname, &i) == 2) {
if (!strcmp(vname, "y")) {
strcpy(texname, "y");
} else {
tex_escape(vnesc, vname);
if (!inmath) {
strcpy(texname, vnesc);
} else {
sprintf(texname, "\\mbox{%s}", vnesc);
}
}
if (!inmath) {
sprintf(targ, "%s$_{t-%d}$", texname, i);
} else {
sprintf(targ, "%s_{t-%d}", texname, i);
}
} else {
tex_escape(vnesc, src);
strcpy(targ, vnesc);
}
} else {
tex_escape(vnesc, src);
strcpy(targ, vnesc);
}
}
static void tex_VAR_varname (char *s, const MODEL *pmod,
const DATASET *dset, int v)
{
char tmp[32], base[12];
int lag;
gretl_model_get_param_name(pmod, dset, v, tmp);
if (sscanf(tmp, "%11[^_]_%d", base, &lag) == 2) {
sprintf(s, "%s$_{t-%d}$", base, lag);
} else {
tex_escape(s, tmp);
}
}
static void tex_VECM_varname (char *s, const MODEL *pmod,
const DATASET *dset, int v)
{
char tmp[32], base[12];
int lag;
gretl_model_get_param_name(pmod, dset, v, tmp);
if (sscanf(tmp, "d_%11[^_]_%d", base, &lag) == 2) {
sprintf(s, "$\\Delta$%s$_{t-%d}$", base, lag);
} else {
tex_escape(s, tmp);
}
}
static int tex_print_coeff_custom (const model_coeff *mc, PRN *prn)
{
char fmt[12];
pprintf(prn, "%s & ", mc->name);
if (colspec[0][0]) {
/* coefficient */
if (na(mc->b)) {
pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
} else {
sprintf(fmt, "$%s$", colspec[0]);
pprintf(prn, fmt, mc->b);
}
}
if (!colspec[1][0] && !colspec[2][0] && !colspec[3][0]) {
pputs(prn, " \\\\\n");
return 0;
}
if (colspec[1][0]) {
if (colspec[0][0]) {
pputs(prn, " & ");
}
/* standard error */
if (na(mc->se)) {
pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
} else {
pprintf(prn, colspec[1], mc->se);
}
}
if (!colspec[2][0] && !colspec[3][0]) {
pputs(prn, " \\\\\n");
return 0;
}
if (colspec[2][0]) {
if (colspec[0][0] || colspec[1][0]) {
pputs(prn, " & ");
}
/* t-ratio */
if (na(mc->tval)) {
if (mc->show_tval) {
pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
} else {
pprintf(prn, "\\multicolumn{1}{c}{}");
}
} else {
sprintf(fmt, "$%s$", colspec[2]);
pprintf(prn, fmt, mc->tval);
}
}
if (colspec[3][0]) {
if (colspec[0][0] || colspec[1][0] || colspec[2][0]) {
pputs(prn, " & ");
}
/* p-value (or perhaps slope) */
if (mc->show_pval) {
if (na(mc->pval)) {
pprintf(prn, "\\multicolumn{1}{c}{\\rm %s}", _("undefined"));
} else {
pprintf(prn, colspec[3], mc->pval);
}
} else if (!na(mc->slope)) {
pprintf(prn, colspec[3], mc->slope);
} else {
pprintf(prn, "\\multicolumn{1}{c}{}");
}
}
pputs(prn, " \\\\\n");
return 0;
}
void make_tex_coeff_name (const MODEL *pmod, const DATASET *dset, int i,
char *name)
{
char pname[VNAMELEN];
gretl_model_get_param_name(pmod, dset, i, pname);
if (pmod->aux == AUX_ARCH) {
tex_make_cname(name, pname);
} else if (pmod->ci == NLS) {
if (!tex_greek_param(name, pname)) {
tex_escape(name, pname);
}
} else if (pmod->ci == ARMA) {
tex_arma_coeff_name(name, pname, 0);
} else if (pmod->ci == GARCH) {
tex_garch_coeff_name(name, pname, 0);
} else if (pmod->ci == VAR) {
tex_VAR_varname(name, pmod, dset, i);
} else if (pmod->aux == AUX_VECM) {
tex_VECM_varname(name, pmod, dset, i);
} else if (pmod->ci == MPOLS) {
tex_mp_coeff_name(name, pname, 0);
} else {
tex_escape(name, pname);
}
}
static char *tex_multi_double (double x, char *numstr)
{
char *p;
if (na(x)) {
strcpy(numstr, " ");
} else if (x < 0) {
sprintf(numstr, "$-$%.15E", -x);
} else {
sprintf(numstr, "%.15E", x);
}
if ((p = strstr(numstr, "E-")) != NULL) {
char tmp[8];
sprintf(tmp, "E--%s", p + 2);
strcpy(p, tmp);
}
return numstr;
}
void tex_print_coeff (const model_coeff *mc, PRN *prn)
{
char col1[64], col2[64], col3[64], col4[64];
int ncols = 4;
if (mc->multi) {
tex_multi_double(mc->b, col1);
tex_multi_double(mc->se, col2);
pprintf(prn, "%s & %s & %s \\\\\n", mc->name, col1, col2);
return;
}
if (use_custom) {
tex_print_coeff_custom(mc, prn);
return;
}
if (na(mc->b)) {
sprintf(col1, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
} else {
tex_rl_double(mc->b, col1);
}
if (!na(mc->lo) && !na(mc->hi)) {
tex_rl_double(mc->lo, col2);
tex_rl_double(mc->hi, col3);
ncols = 3;
} else {
if (na(mc->se)) {
sprintf(col2, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
} else {
tex_rl_double(mc->se, col2);
}
if (na(mc->tval)) {
if (mc->show_tval) {
sprintf(col3, "\\multicolumn{2}{c}{\\rm %s}", _("undefined"));
} else {
strcpy(col3, "\\multicolumn{2}{c}{}");
}
} else {
/* note: was tex_rl_float(mc->tval, col3, 4) */
tex_rl_double_dig(mc->tval, col3, 4);
}
}
*col4 = '\0';
if (!mc->show_pval && na(mc->slope)) {
strcpy(col4, "\\multicolumn{2}{c}{}");
} else if (!na(mc->slope)) {
tex_rl_double(mc->slope, col4);
} else if (mc->show_pval) {
if (!na(mc->pval)) {
tex_rl_float(mc->pval, col4, 4);
}
}
pprintf(prn, "%s &\n"
" %s &\n"
" %s &\n",
mc->name,
col1,
col2);
if (ncols == 4) {
pprintf(prn,
" %s &\n"
" %s \\\\\n",
col3,
col4);
} else {
pprintf(prn,
" %s \\\\\n",
col3);
}
}
static int
tex_custom_coeff_table_start (const char **cols, gretlopt opt, PRN *prn)
{
int i, ncols = 0;
for (i=0; i<4; i++) {
if (colspec[i][0]) {
ncols++;
}
}
if (!(opt & OPT_U)) {
/* not a user-defined model */
pputs(prn, "\\vspace{1em}\n\n");
}
pputs(prn, "\\begin{tabular}{l");
for (i=0; iylist;
double x;
int i, j;
pprintf(prn, "%s\n\n", _("Cross-equation covariance matrix"));
pputs(prn, "\\vspace{1em}\n");
pputs(prn, "\\begin{tabular}{");
pputs(prn, "l");
for (i=0; ineqns; i++) {
pputs(prn, "r");
}
pputs(prn, "}\n & ");
for (i=0; ineqns; i++) {
tex_escape(vname, dset->varname[list[i+1]]);
pprintf(prn, "$\\Delta$%s ", vname);
if (i == vecm->neqns - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, "& ");
}
}
pputc(prn, '\n');
for (i=0; ineqns; i++) {
tex_escape(vname, dset->varname[list[i+1]]);
pprintf(prn, "$\\Delta$%s & ", vname);
for (j=0; jneqns; j++) {
x = gretl_matrix_get(vecm->S, i, j);
tex_print_double(x, prn);
if (j == vecm->neqns - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, " & ");
}
}
}
pputs(prn, "\\end{tabular}\n\n");
pputs(prn, "\\vspace{1em}\n");
pputs(prn, "\\noindent\n");
pprintf(prn, "%s = ", _("determinant"));
tex_print_double(exp(vecm->ldet), prn);
pputs(prn, "\\\\\n");
}
static void tex_beta_vname (char *s,
const GRETL_VAR *v,
const DATASET *dset,
int i, PRN *prn)
{
if (i < v->neqns) {
tex_escape(s, dset->varname[v->ylist[i+1]]);
pprintf(prn, "%s$_{t-1}$ & ", s);
} else if (auto_restr(v) && i == v->neqns) {
pprintf(prn, "%s & ", (jcode(v) == J_REST_CONST)? "const" : "trend");
} else if (v->rlist != NULL) {
int k = i - v->ylist[0] - auto_restr(v) + 1;
tex_escape(s, dset->varname[v->rlist[k]]);
pprintf(prn, "%s$_{t-1}$ & ", s);
}
}
void tex_print_VECM_coint_eqns (GRETL_VAR *vecm, const DATASET *dset, PRN *prn)
{
char s[32];
JohansenInfo *jv = vecm->jinfo;
int rows = gretl_matrix_rows(jv->Beta);
int i, j;
double x;
pputs(prn, "\\noindent\n");
pputs(prn, _("Cointegrating vectors"));
if (jv->Bse != NULL) {
pprintf(prn, " (%s)\n", _("standard errors in parentheses"));
} else {
pputc(prn, '\n');
}
pputs(prn, "\n\\vspace{1em}\n");
pputs(prn, "\\begin{tabular}{");
pputs(prn, "l");
for (i=0; irank; i++) {
pputs(prn, "r");
}
pputs(prn, "}\n");
for (i=0; irank; j++) {
x = gretl_matrix_get(jv->Beta, i, j);
if (jv->Bse == NULL) {
x /= gretl_matrix_get(jv->Beta, j, j);
}
tex_print_double(x, prn);
if (j == jv->rank - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, "& ");
}
}
if (jv->Bse != NULL) {
/* standard errors */
pputs(prn, " & ");
for (j=0; jrank; j++) {
x = gretl_matrix_get(jv->Bse, i, j);
pputc(prn, '(');
tex_print_double(x, prn);
pputc(prn, ')');
if (j == jv->rank - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, "& ");
}
}
}
}
pputs(prn, "\\end{tabular}\n\n\\vspace{1em}\n");
pputc(prn, '\n');
rows = gretl_matrix_rows(jv->Alpha);
pputs(prn, "\\noindent\n");
pprintf(prn, _("Adjustment vectors"));
if (jv->Ase != NULL) {
pprintf(prn, " (%s)\n", _("standard errors in parentheses"));
} else {
pputc(prn, '\n');
}
pputs(prn, "\n\\vspace{1em}\n");
pputs(prn, "\\begin{tabular}{");
pputs(prn, "l");
for (i=0; irank; i++) {
pputs(prn, "r");
}
pputs(prn, "}\n");
for (i=0; irank; j++) {
x = gretl_matrix_get(jv->Alpha, i, j);
if (jv->Ase == NULL) {
x /= gretl_matrix_get(jv->Alpha, j, j);
}
tex_print_double(x, prn);
if (j == jv->rank - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, "& ");
}
}
if (jv->Ase != NULL) {
/* standard errors */
pputs(prn, " & ");
for (j=0; jrank; j++) {
x = gretl_matrix_get(jv->Ase, i, j);
pputc(prn, '(');
tex_print_double(x, prn);
pputc(prn, ')');
if (j == jv->rank - 1) {
pputs(prn, "\\\\\n");
} else {
pputs(prn, "& ");
}
}
}
}
pputs(prn, "\\end{tabular}\n\n\\vspace{1em}\n");
pputc(prn, '\n');
}
void tex_print_VAR_ll_stats (GRETL_VAR *var, PRN *prn)
{
pprintf(prn, "\\noindent\n%s = ", _("Log-likelihood"));
tex_print_double(var->ll, prn);
pputs(prn, "\\par\n");
pprintf(prn, "\\noindent\n%s = ", _("Determinant of covariance matrix"));
tex_print_double(exp(var->ldet), prn);
pputs(prn, "\\par\n");
pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("AIC"), var->AIC);
pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("BIC"), var->BIC);
pprintf(prn, "\\noindent\n%s $= %.4f$ \\par\n", _("HQC"), var->HQC);
}
static PRN *make_tex_prn (const char *fname,
int eqn, int doc,
int *err)
{
PrnFormat fmt = GRETL_FORMAT_TEX;
PRN *prn;
gretl_maybe_switch_dir(fname);
prn = gretl_print_new_with_filename(fname, err);
if (prn != NULL) {
if (eqn) {
fmt |= GRETL_FORMAT_EQN;
}
if (doc) {
fmt |= GRETL_FORMAT_DOC;
}
gretl_print_set_format(prn, fmt);
}
return prn;
}
/* mechanism for customizing gretl's tex preamble */
static char tex_preamble_file[MAXLEN];
static const char *set_tex_locale_filename (char *local)
{
char *lang = getenv("LANG");
*local = '\0';
if (lang != NULL) {
char lstr[3] = {0};
strncat(lstr, lang, 2);
sprintf(local, "gretlpre_%s.tex", lstr);
}
return local;
}
static int find_gretlpre (const char *path, const char *localname)
{
char test[MAXLEN];
int err, gotit = 0;
if (*localname != '\0') {
/* localized preamble file? */
sprintf(test, "%s%s", path, localname);
err = gretl_test_fopen(test, "r");
if (!err) {
strcpy(tex_preamble_file, test);
gotit = 1;
}
}
if (!gotit) {
/* regular preamble file? */
sprintf(test, "%sgretlpre.tex", path);
err = gretl_test_fopen(test, "r");
if (!err) {
strcpy(tex_preamble_file, test);
gotit = 1;
}
}
return gotit;
}
void set_gretl_tex_preamble (void)
{
const char *path = gretl_workdir();
char localname[16];
int gotit;
set_tex_locale_filename(localname);
gotit = find_gretlpre(path, localname);
if (!gotit) {
path = maybe_get_default_workdir();
if (path != NULL) {
gotit = find_gretlpre(path, localname);
}
}
if (!gotit) {
#ifdef OS_OSX
path = gretl_app_support_dir();
#else
path = gretl_dotdir();
#endif
gotit = find_gretlpre(path, localname);
}
gretl_error_clear();
}
static void landscape_modify_line (char *line)
{
char *p, *rem;
if (strstr(line, "landscape")) {
return;
}
p = strstr(line, "documentclass");
if (p != NULL) {
if (*(p + 13) == '[') {
p = strchr(p, ']');
if (p != NULL) {
rem = gretl_strdup(p);
if (rem != NULL) {
sprintf(p, ",landscape%s", rem);
free(rem);
}
}
} else {
p += 13;
rem = gretl_strdup(p);
if (rem != NULL) {
sprintf(p, "[landscape]%s", rem);
free(rem);
}
}
}
}
void gretl_tex_preamble (PRN *prn, int fmt)
{
char *lang = getenv("LANG");
FILE *fp = NULL;
int userfile = 0;
if (*tex_preamble_file != '\0') {
fp = gretl_fopen(tex_preamble_file, "r");
if (fp != NULL) {
char line[256];
/* FIXME model table: longtable and geom packages */
while (fgets(line, sizeof line, fp)) {
if (strstr(line, "documentclass") &&
(fmt & GRETL_FORMAT_LANDSCAPE)) {
landscape_modify_line(line);
}
pputs(prn, line);
}
userfile = 1;
fclose(fp);
fprintf(stderr, "gretltex: using preamble file\n %s\n",
tex_preamble_file);
}
}
if (!userfile) {
const char *paper = in_usa()? "letterpaper" : "a4paper";
const char *driver = use_pdf ? "pdftex" : "dvips";
const char *margin = "";
if (fmt & GRETL_FORMAT_MODELTAB) {
margin = "margin=2cm,";
}
pputs(prn, "\\documentclass");
if (fmt & GRETL_FORMAT_MODELTAB) {
if (fmt & GRETL_FORMAT_LANDSCAPE) {
pputs(prn, "[landscape]");
}
} else if (fmt & GRETL_FORMAT_LANDSCAPE) {
pputs(prn, "[11pt,landscape]");
} else {
pputs(prn, "[11pt]");
}
pputs(prn, "{article}\n");
#ifdef ENABLE_NLS
pputs(prn, "\\usepackage[utf8]{inputenc}\n");
#endif
if (lang != NULL && !strncmp(lang, "ru", 2)) {
pputs(prn, "\\usepackage[russian]{babel}\n");
}
pprintf(prn, "\\usepackage[%s,%s%s]{geometry}\n", paper, margin,
driver);
if (fmt & GRETL_FORMAT_EQN) {
pputs(prn, "\\usepackage{amsmath}\n");
} else {
pputs(prn, "\\usepackage{longtable}\n");
}
pputs(prn, "\n\\begin{document}\n\n"
"\\thispagestyle{empty}\n\n");
}
}
/* For use when printing a model in equation style: print the value
unsigned, since the sign will be handled separately.
*/
static void tex_print_unsigned_double (double x, PRN *prn)
{
tex_print_double(fabs(x), prn);
}
#define MAXCOEFF 4
/**
* tex_print_equation:
* @pmod: pointer to gretl MODEL struct.
* @dset: information regarding the data set.
* @opt: can include %OPT_S for a standalone document, and
* %OPT_T to print t-ratios rather than standard errors.
* @prn: gretl printing struct.
*
* Prints to @prn a gretl model in the form of a LaTeX equation, either as
* a stand-alone document or as a fragment of LaTeX source for
* insertion into a document.
*
* Returns: 0 on successful completion.
*/
int tex_print_equation (const MODEL *pmod, const DATASET *dset,
gretlopt opt, PRN *prn)
{
double x;
char tmp[48], vname[32];
int i, nc = pmod->ncoeff;
int split = 0, offvar = 0;
int cchars = 0, ccount = 0;
int se_digits;
int sderr_ok = 1;
if (pmod->ci == HECKIT) {
return E_NOTIMP;
}
if (COUNT_MODEL(pmod->ci)) {
offvar = gretl_model_get_int(pmod, "offset_var");
if (offvar > 0) {
nc++;
}
}
split = (nc > MAXCOEFF);
if (opt & OPT_S) {
gretl_tex_preamble(prn, GRETL_FORMAT_EQN);
} else{
pputs(prn, "%%% the following needs the amsmath LaTeX package\n\n");
}
/* initial setup */
pputs(prn, "\\begin{gather}\n");
if (split) {
pputs(prn, "\\begin{split}\n");
}
/* dependent variable */
*tmp = '\0';
if (pmod->depvar != NULL) {
tex_escape(tmp, pmod->depvar);
} else {
i = gretl_model_get_depvar(pmod);
tex_escape(tmp, dset->varname[i]);
}
if (0 /* FIXME should this apply for DPANEL? (was ARBOND-specific) */) {
pprintf(prn, "\\widehat{\\Delta \\rm %s} %s= \n", tmp, (split? "&" : ""));
} else {
pprintf(prn, "\\widehat{\\rm %s} %s= \n", tmp, (split? "&" : ""));
}
if (pmod->ci == GARCH) {
nc -= (1 + pmod->list[1] + pmod->list[2]);
} else if (pmod->ci == PANEL) {
nc = pmod->list[0] - 1;
}
se_digits = get_gretl_digits();
se_digits = se_digits > 5 ? 5 : se_digits;
/* coefficients times indep vars */
for (i=0; i 0 && i == nc - 1) {
pputc(prn, '+');
tex_print_double(1.0, prn);
} else {
if (na(pmod->sderr[i])) {
sderr_ok = 0;
pprintf(prn, "%s{", (pmod->coeff[i] < 0.0)? "-" :
(i > 0)? "+" : "");
} else if (sderr_ok) {
if (opt & OPT_T) {
/* t-ratios */
x = pmod->coeff[i] / pmod->sderr[i];
pprintf(prn, "%s\\underset{(%.3f)}{",
(pmod->coeff[i] < 0.0)? "-" :
(i > 0)? "+" : "", x);
} else {
/* standard errors */
tex_sprint_math_double_digits(pmod->sderr[i], tmp, se_digits);
pprintf(prn, "%s\\underset{(%s)}{",
(pmod->coeff[i] < 0.0)? "-" :
(i > 0)? "+" : "", tmp);
}
}
tex_print_unsigned_double(pmod->coeff[i], prn);
pputc(prn, '}');
}
if (i > 0 || pmod->ifc == 0) {
/* regular coefficient, not const */
if (offvar > 0 && i == nc - 1) {
strcpy(vname, dset->varname[offvar]);
} else {
gretl_model_get_param_name(pmod, dset, i, vname);
}
cchars += strlen(vname);
pputs(prn, "\\,");
if (pmod->ci == ARMA) {
tex_arma_coeff_name(tmp, vname, 1);
pputs(prn, tmp);
} else if (pmod->ci == GARCH) {
tex_garch_coeff_name(tmp, vname, 1);
pputs(prn, tmp);
} else if (pmod->ci == MPOLS) {
tex_mp_coeff_name(tmp, vname, 1);
pputs(prn, tmp);
} else {
tex_escape(tmp, vname);
pprintf(prn, "\\mbox{%s}", tmp);
}
}
ccount++;
if (split && (cchars > 30 || ccount > 3)) {
pputs(prn, "\\\\\n& ");
cchars = ccount = 0;
} else {
pputc(prn, '\n');
}
}
if (split) {
pputs(prn, "\\end{split}\n");
}
pputs(prn, " \\notag \\\\\n");
if (pmod->ci == GARCH) {
int q = pmod->list[1];
int p = pmod->list[2];
int r = pmod->list[0] - 4;
if (opt & OPT_T) {
x = pmod->coeff[r] / pmod->sderr[r];
pprintf(prn, "\\hat{\\sigma}^2_t = \\underset{(%.3f)}{%g} ",
x, pmod->coeff[r]);
} else {
tex_sprint_math_double_digits(pmod->sderr[r], tmp, se_digits);
pprintf(prn, "\\hat{\\sigma}^2_t = \\underset{(%s)}{%g} ", /* FIXME? */
tmp, pmod->coeff[r]);
}
for (i=1; i<=q; i++) {
if (opt & OPT_T) {
x = pmod->coeff[r+i] / pmod->sderr[r+i];
pprintf(prn, "%s\\underset{(%.3f)}{",
(pmod->coeff[r+i] < 0.0)? "-" : "+", x);
} else {
tex_sprint_math_double_digits(pmod->sderr[r+i], tmp, se_digits);
pprintf(prn, "%s\\underset{(%s)}{",
(pmod->coeff[r+i] < 0.0)? "-" : "+", tmp);
}
tex_print_unsigned_double(pmod->coeff[r+i], prn);
pputs(prn, "}\\,");
pprintf(prn, "\\varepsilon^2_{t-%d}", i);
}
for (i=1; i<=p; i++) {
if (opt & OPT_T) {
x = pmod->coeff[q+r+i] / pmod->sderr[q+r+i];
pprintf(prn, "%s\\underset{(%.3f)}{",
(pmod->coeff[q+r+i] < 0.0)? "-" : "+", x);
} else {
tex_sprint_math_double_digits(pmod->sderr[q+r+i], tmp, se_digits);
pprintf(prn, "%s\\underset{(%s)}{",
(pmod->coeff[q+r+i] < 0.0)? "-" : "+", tmp);
}
tex_print_unsigned_double(pmod->coeff[q+r+i], prn);
pputs(prn, "}\\,");
pprintf(prn, "\\sigma^2_{t-%d}", i);
}
pputs(prn, "\\notag \\\\\n");
}
pprintf(prn, "T = %d ", pmod->nobs);
/* additional info (R^2 etc) */
if (pmod->ci == LAD) {
x = gretl_model_get_double(pmod, "ladsum");
if (!na(x)) {
tex_sprint_math_double_digits(x, tmp, 5);
pprintf(prn, "\\quad \\sum |\\hat{u}_t| = %s ", tmp);
}
} else {
if (!na(pmod->adjrsq)) {
pprintf(prn, "\\quad \\bar{R}^2 = %.4f ", pmod->adjrsq);
} else if (!na(pmod->lnL)) {
pprintf(prn, "\\quad \\mbox{ln}L = %.4f ", pmod->lnL);
}
if (pmod->ci != LOGIT && pmod->ci != PROBIT && !na(pmod->fstt)) {
tex_sprint_math_double_digits(pmod->fstt, tmp, 5);
pprintf(prn, "\\quad F(%d,%d) = %s ",
pmod->dfn, pmod->dfd, tmp);
}
if (!na(pmod->sigma)) {
tex_sprint_math_double_digits(pmod->sigma, tmp, 5);
pprintf(prn, "\\quad \\hat{\\sigma} = %s ", tmp);
}
if (!na(gretl_model_get_double(pmod, "rho_gls"))) {
x = gretl_model_get_double(pmod, "rho_gls");
tex_sprint_math_double_digits(x, tmp, 5);
pprintf(prn, " \\quad \\rho = %s", tmp);
}
}
pputs(prn, "\\notag \\\\\n");
if (sderr_ok) {
pprintf(prn, "\\centerline{(%s)} \\notag\n",
(opt & OPT_T)? _("$t$-statistics in parentheses") :
_("standard errors in parentheses"));
} else {
pputs(prn, "\\notag\n");
}
pputs(prn, "\\end{gather}\n");
if (opt & OPT_S) {
pputs(prn, "\n\\end{document}\n");
}
return 0;
}
/**
* tex_print_model:
* @pmod: pointer to gretl MODEL struct.
* @dset: information regarding the data set.
* @opt: may include %OPT_T in case of printing a model
* in equation format, to use t-ratios instead of standard
* errors.
* @prn: gretl printing struct.
*
* Prints to @prn a gretl model in the form of either a LaTeX
* table or an equation, and either as a stand-alone document or
* as a fragment of LaTeX source for insertion into a document.
*
* The options are read from the format field of @prn --
* gretl_print_set_format().
*
* Returns: 0 on successful completion.
*/
int tex_print_model (MODEL *pmod, const DATASET *dset,
gretlopt opt, PRN *prn)
{
int err = 0;
if (RQ_SPECIAL_MODEL(pmod)) {
return E_NOTIMP;
}
if (tex_doc_format(prn)) {
opt |= OPT_S;
}
if (tex_eqn_format(prn)) {
err = tex_print_equation(pmod, dset, opt, prn);
} else {
if (opt & OPT_T) {
/* --format option */
const char *s = get_optval_string(TABPRINT, OPT_T);
err = set_tex_param_format(s);
}
if (!err) {
err = printmodel(pmod, dset, OPT_NONE, prn);
}
}
return err;
}
/**
* texprint:
* @pmod: pointer to model.
* @dset: information regarding the data set.
* @fname: name of file to save.
* @opt: if opt & %OPT_O, complete doc, else fragment;
* if opt & %OPT_E print as equation, otherwise use tabular
* format; if opt & %OPT_T show t-ratios rather than standard
* errors when printing in equation format.
*
* Prints to file a gretl model in the form of a LaTeX table or
* equation, either as a stand-alone document or as a fragment
* of LaTeX source for insertion into a document.
*
* Returns: 0 on successful completion, 1 on error.
*/
int texprint (MODEL *pmod, const DATASET *dset,
const char *fname, gretlopt opt)
{
PRN *prn;
int eqn = (opt & OPT_E);
int doc = (opt & OPT_O);
int err = 0;
if (RQ_SPECIAL_MODEL(pmod)) {
return E_NOTIMP;
}
prn = make_tex_prn(fname, eqn, doc, &err);
if (!err) {
err = tex_print_model(pmod, dset, opt, prn);
gretl_print_destroy(prn);
}
return err;
}
static void out_crlf (const char *buf, FILE *fp)
{
const char *p = buf;
#ifdef G_OS_WIN32
/* fputs on Windows should take care of CR, LF */
fputs(p, fp);
#else
while (*p) {
if (*p == '\n') {
fputs("\r\n", fp);
} else {
fputc(*p, fp);
}
p++;
}
#endif
}
int rtfprint (MODEL *pmod, const DATASET *dset,
const char *fname, gretlopt opt)
{
const char *buf = NULL;
char *trbuf = NULL;
PRN *prn;
int err = 0;
if (RQ_SPECIAL_MODEL(pmod)) {
return E_NOTIMP;
}
prn = gretl_print_new(GRETL_PRINT_BUFFER, &err);
if (!err) {
/* print the model to buffer first */
gretl_print_set_format(prn, GRETL_FORMAT_RTF);
err = printmodel(pmod, dset, opt, prn);
}
if (!err) {
/* recode if necessary */
buf = gretl_print_get_buffer(prn);
if (!gretl_is_ascii(buf)) {
trbuf = utf8_to_rtf(buf);
if (trbuf == NULL) {
err = E_ALLOC;
}
}
}
if (!err) {
/* now send to file, converting LF to CR + LF
as we go, if required
*/
FILE *fp;
gretl_maybe_switch_dir(fname);
fp = gretl_fopen(fname, "w");
if (fp == NULL) {
err = E_FOPEN;
} else if (trbuf != NULL) {
out_crlf(trbuf, fp);
} else {
out_crlf(buf, fp);
}
if (fp != NULL) {
fclose(fp);
}
}
if (trbuf != NULL) {
free(trbuf);
}
if (prn != NULL) {
gretl_print_destroy(prn);
}
return err;
}
static void out_native (const char *buf, FILE *fp)
{
#ifdef G_OS_WIN32
if (!gretl_is_ascii(buf)) {
/* Windows: if the text is UTF-8, prepend
the UTF-8 BOM */
fputc(0xEF, fp);
fputc(0xBB, fp);
fputc(0xBF, fp);
}
#endif
fputs(buf, fp);
}
int csvprint (MODEL *pmod, const DATASET *dset,
const char *fname, gretlopt opt)
{
PRN *prn;
int err = 0;
if (RQ_SPECIAL_MODEL(pmod)) {
return E_NOTIMP;
}
prn = gretl_print_new(GRETL_PRINT_BUFFER, &err);
if (!err) {
/* print to buffer first */
gretl_print_set_format(prn, GRETL_FORMAT_CSV);
err = printmodel(pmod, dset, opt, prn);
}
if (!err) {
/* then send to file */
const char *buf = gretl_print_get_buffer(prn);
FILE *fp;
gretl_maybe_switch_dir(fname);
fp = gretl_fopen(fname, "w");
if (fp == NULL) {
err = E_FOPEN;
} else {
out_native(buf, fp);
}
if (fp != NULL) {
fclose(fp);
}
}
if (prn != NULL) {
gretl_print_destroy(prn);
}
return err;
}
/**
* tex_print_obs_marker:
* @t: observation number.
* @dset: data information struct.
* @prn: gretl printing struct.
*
* Print a string (label, date or obs number) representing the given @t.
*/
void tex_print_obs_marker (int t, const DATASET *dset, PRN *prn)
{
if (dset->markers) {
pprintf(prn, "\\texttt{%s} ", dset->S[t]);
} else {
char tmp[OBSLEN];
ntolabel(tmp, t, dset);
pprintf(prn, "%8s ", tmp);
}
}
static int check_colspec (const char *s)
{
const char *ok = "eEfgG";
int w = 0, p = 0;
char c = 0;
int err = 1;
/* blank is OK */
if (*s == '\0') {
return 0;
}
if (*s != '%') {
return 1;
}
s++;
if (*s == '#') { /* OK */
s++;
}
if (sscanf(s, "%d.%d%c", &w, &p, &c) == 3) {
if (w != 0 && p > 0 && strchr(ok, c)) {
err = 0;
}
} else if (sscanf(s, "%d%c", &w, &c) == 2) {
if (w != 0 && strchr(ok, c)) {
err = 0;
}
} else if (sscanf(s, ".%d%c", &p, &c) == 2) {
if (p > 0 && strchr(ok, c)) {
err = 0;
}
} else if (sscanf(s, "%c", &c) == 1) {
if (strchr(ok, c)) {
err = 0;
}
}
return err;
}
/**
* set_tex_param_format:
* @s: stylized format string.
*
* Sets the format with which parameters will be printed, when
* producing TeX tabular output.
*
* Returns: 0 on success, non-zero code on error.
*/
int set_tex_param_format (const char *s)
{
const char *p = s;
int i, n = 0;
int err = 0;
if (s == NULL || !strcmp(s, "default")) {
use_custom = 0;
return 0;
}
for (i=0; i<4; i++) {
colspec[i][0] = '\0';
}
i = 0;
while (i < 4) {
if (*s == '|' || *s == '\0') {
if (n > 7) {
n = 7;
}
strncat(colspec[i], p, n);
#if 0
fprintf(stderr, "spec %d = '%s'\n", i, colspec[i]);
#endif
err = check_colspec(colspec[i]);
if (err || *s == '\0') {
break;
}
p = s + 1;
i++;
n = 0;
} else {
n++;
}
s++;
}
if (!err) {
/* all columns can't be blank */
n = 0;
for (i=0; i<4; i++) {
if (colspec[i][0] != '\0') n++;
}
if (n == 0) {
err = E_ARGS;
}
}
if (err) {
for (i=0; i<4; i++) {
colspec[i][0] = '\0';
}
use_custom = 0;
} else {
use_custom = 1;
}
return err;
}