4

For a paper, I have to present two code snippets that do the same thing to compare them.

I started having them in two different figures, but now, I'm trying to have them side by side, and that's where the trouble starts.

First of all, I couldn't seem to get listings to work in subfig.

\lstset{%
language=C,
frame=single,
numbers=left,
numberstyle=\footnotesize,
tabsize=2,
keepspaces=true,
columns=fullflexible,
basicstyle=\ttfamily,
keywordstyle=\color{blue}
}


\begin{figure}
\subfloat[small code]{%
\begin{lstlisting}
for(int i = 0 ; i < N ; i++)
 for(int j = 0 ; j < N ; j++)
  for(int k = 0 ; k < N ; k++)
   c[i][j] += a[i][k] * b[k][j];
\end{lstlisting}
}
\hfill
\subfloat[Larger code]{%
\begin{lstlisting}
for(int ii = 0 ; ii < N ; ii+=B) {
 for(int jj = 0 ; jj < N ; jj+=B) {
  for(int kk = 0 ; kk < N ; kk+=B) {
   for(int i = ii ; i < ii + B ; i++) {
    for(int k = kk ; k < kk + B ; k++){
     c_i = c[i];
     a_ik = a[i][k];
     b_k = b[k];
     for(int j = jj ; j < jj + B ; j+=2){
      c_i[j] += a_ik * b_k[j];
      c_i[j+1] += a_ik * b_k[j+1];
     }
    }
   }
  }
 }
}
\end{lstlisting}
}
\end{figure}

This, generates a score of errors that I can't make sense of. After browsing the web, I found that a lot of people seem to achieve what I want to do by including the source code from an external file.

\begin{figure}[!htb]
\subfloat[Toto]{%
\lstinputlisting{mm_base.c}%
}
\hfill
\subfloat[Tata]{%
\lstinputlisting{mm_opt.c}%
}
\end{figure}

By manually changing the fontsize, I can get the subfloats to be side by side, but I get the following result:

Bad Frames

The frame around the code and the perceived size of the content don't seem to match. Moreover, the code on the right hand side goes out of bound, the right frame goes off-page.

The first thing I'd like to know, out of curiosity really, is why I can't use the lstlisting environment and only the lstinputlisting when inside a subfloat.

And the more pressing matters, getting the frame to match the subfig's width. And the more challenging part maybe, automatically change the size of the code included to fit in the subfig.

2
  • A little late Welcome to TeX.sx! to you. Please note that we prefer a full, compilable, but minimal working example (MWE) that illustrates the problem. Often it is hard to see which package are required etc. without it. Also people can just add their solutions quickly and test them. Jun 24, 2011 at 16:57
  • Thanks :) I'll make sure to add the extra wrapping code to make my samples compilable next time.
    – Lexiel
    Jun 24, 2011 at 18:19

1 Answer 1

6

You need to reduce the \linewidth before using \lstinputlisting, otherwise it uses the full normal line width.

You can do this using \parbox or minipage environment. For example the following code places the listing in a paragraph box with 48% of the normal line width. (Some people use \textwidth which is mostly the same.)

\parbox{.48\linewidth}{\lstinputlisting{file.c}}

The reason why your first example doesn't work is that lstlisting is a verbatim environment and therefore not allowed in arguments of other macros. This is because the code is read as part of the argument before \begin{lstlisting} is processed and tells LaTeX to thread the code verbatim!

If you want to have the code in the main file, you could store the listings in a box which is then used in the \subfloat. This requires minipage because \parbox would also read the listing as macro argument.

\documentclass{article}

\usepackage{xcolor}
\usepackage{subfig}
\usepackage{listings}

\lstset{%
language=C,
frame=single,
numbers=left,
numberstyle=\footnotesize,
tabsize=2,
keepspaces=true,
columns=fullflexible,
basicstyle=\ttfamily\scriptsize,
keywordstyle=\color{blue}
}

\newsavebox{\mylistingbox}

\begin{document}

\begin{figure}

\begin{lrbox}{\mylistingbox}%
\begin{minipage}{.45\linewidth}%
\begin{lstlisting}
for(int i = 0 ; i < N ; i++)
 for(int j = 0 ; j < N ; j++)
  for(int k = 0 ; k < N ; k++)
   c[i][j] += a[i][k] * b[k][j];
\end{lstlisting}%
\end{minipage}%
\end{lrbox}%
%
\subfloat[small code]{\usebox{\mylistingbox}}%
%
\hfill
%
\begin{lrbox}{\mylistingbox}%
\begin{minipage}{.45\linewidth}%
\begin{lstlisting}
for(int ii = 0 ; ii < N ; ii+=B) {
 for(int jj = 0 ; jj < N ; jj+=B) {
  for(int kk = 0 ; kk < N ; kk+=B) {
   for(int i = ii ; i < ii + B ; i++) {
    for(int k = kk ; k < kk + B ; k++){
     c_i = c[i];
     a_ik = a[i][k];
     b_k = b[k];
     for(int j = jj ; j < jj + B ; j+=2){
      c_i[j] += a_ik * b_k[j];
      c_i[j+1] += a_ik * b_k[j+1];
     }
    }
   }
  }
 }
}
\end{lstlisting}%
\end{minipage}%
\end{lrbox}%
%
\subfloat[Larger code]{\usebox{\mylistingbox}}%

\end{figure}

\end{document}

I reduces the font size here to fit both on the normal text width. For figures you could also extend it in the margin using the technique shown be me in Center figure that is wider than \textwidth and Place figures side by side, spill into outer margin. In your case either use two box registers and then:

\makebox[1.2\textwidth]{\subfloat[Shorter code]{\usebox{\mylistingboxa}}\hfill\subfloat[Larger code]{\usebox{\mylistingboxb}}}

or add the following equivalent lines before and after the whole subfloat related code:

\hbox to 1.2\textwidth\bgroup\hss
 % the whole box saving and \subfloat code above
\hss\egroup 
2
  • Parbox : That does fix the frame, thanks. And it seems like the line numbers are added with a negative offset by default, I hadn't noticed before that they are in the margins. (damn enter key that posts automatically...) When I tried to put a listing inside a savebox I actually had the same problem as when I was trying to put it into a subfloat.
    – Lexiel
    Jun 24, 2011 at 16:49
  • @Lexiel: You need to us the lrbox environment instead of the \sbox macro in this case. See the full example I put now in my answer. Jun 24, 2011 at 16:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.