9

The code

\documentclass{memoir}

\begin{document}
\fontsize{\dimexpr 1.2^{3} 10pt}{\dimexpr 1.2^{3} 10pt}\selectfont Hello TeXworld.
\end{document}

does not work. Why not?

EDIT: I need a solution that supports all integral (including negative) exponents.

Gaussler
  • 12,801
  • 1
    Beyond 'this is not valid syntax for a \dimexpr' I'm not sure what you are after here as an answer! (See for example http://tex.stackexchange.com/questions/88344/references-for-dimexpr-numexpr) – Joseph Wright Jan 21 '15 at 09:00
  • Obviously, I would like someone to correct it to the right syntax. ;-) – Gaussler Jan 21 '15 at 09:01
  • 1
    You can also check out the Expression section in texdoc etex, which says An expression consists of one or more terms of the same type to be added or subtracted; a term of type t consists of a factor of that type, optionally multiplied and/or divided by numeric factors; finally a factor of type t is either a parenthesized subexpression or a quantity (number, etc.) of that type. – TonioElGringo Jan 21 '15 at 09:03
  • apart from dimexpr not having any syntax for power you don't have any multiplication symbol \dimexpr 1.2 10pt would not work either – David Carlisle Jan 21 '15 at 09:52
  • No, but from what I gathered by looking around, it seemed that the multiplication symbols was not used when multiplying lengths by non-integral numbers. Hence I hoped that the } in front would convince TeX that there was an implicit multiplication symbol in front. Can't say I ever really believed it would work, though. – Gaussler Jan 21 '15 at 09:55

2 Answers2

14

e-TeX's \dimexpr only allows a very limited range of items inside the expression. In particular, you can only multiply a dimension by an integer value

\dimexpr 10pt * 5\relax
\dimexpr 10pt * (5 * 5)\relax

Note the fact that the dimension here comes first. As is the case for a TeX register, you can multiply a \dimexpr by a real number by placing it before the expression

1.2\dimexpr 10pt * 5 \relax

Thus for your case you will need a series of expressions, each multiplied by 1.2, or to pre-calculate the factor

\dimexpr1.2\dimexpr1.2\dimexpr1.2\dimexpr 10pt \relax\relax\relax\relax
\dimexpr 1.728\dimexpr 10pt\relax

An alternative approach would be to use the expl3 FPU to do the floating point work, for example

\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \fpeval \fp_eval:n
\cs_new_eq:NN \fptodim \fp_to_dim:n 
\ExplSyntaxOff

then one of

\dimexpr\fpeval{1.2^(3)}\dimexpr 10pt\relax
\dimexpr\fptodim{1.2^(3) * 10}\relax

where the latter uses the fact that the conversion of a float to dimen uses points as the unit. Note that this method supports negative exponents:

\the\dimexpr\fpeval{1.2^(-3)}\dimexpr 10pt\relax % => 5.78703pt
\the\dimexpr\fptodim{1.2^(-3) * 10}\relax        % => 5.78703pt
Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • Is \cs_new_eq:NN the recommended way of populating Expl macros? – yo' Jan 21 '15 at 09:15
  • @yo' You could use \DeclareExpandableDocumentCommand{\fpeval}{m}{\fp_eval:n{#1}} – egreg Jan 21 '15 at 09:17
  • @yo' For the case here of creating a couple of expandable document commands which are equivalent to expl3 code level ones there is not much in it between this and \DeclareExpandableDocumentCommand. – Joseph Wright Jan 21 '15 at 09:17
  • Yes, I know it supports negative exponents. Excellent answer, by the way! I'm currently using your answer. But it never hurts to get David's answer to work for the purpose as well. I plan to keep the acceptance of your answer anyway. – Gaussler Jan 21 '15 at 11:39
9

You need to encode powers as a macro but a simple recursive loop should do the trick

+ve

===: \dimexpr 1.2\dimexpr 1.2\dimexpr 1.2\dimexpr 10pt\relax \relax \relax \relax 
===: 17.27985pt

-ve

===: \dimexpr \dimexpr (\dimexpr (\dimexpr (10pt * 100)/120 \relax  * 100)/120 
\relax  * 100)/120 \relax \relax 
===: 5.78703pt

Log output from

\documentclass{memoir}

\def\powerfactor#1#2#3{%
\ifnum#2=0
\dimexpr#3\expandafter\relax
\else
\afterfi
\powerfactor{#1}{\numexpr#2-1\relax}{#1\dimexpr#3\relax}%
\fi}
\def\afterfi#1\fi{\fi#1}

\def\negpowerfactor#1#2#3{%
\ifnum#2=0
\dimexpr#3\expandafter\relax
\else
\afterfi
\negpowerfactor{#1}{\numexpr#2-1\relax}{\dimexpr(#3 * 100)/\twodp#100.{}{}! \relax}%
\fi}
\def\twodp#1.#2#3#4!{#1#2#3}

\typeout{===: \powerfactor{1.2}{3}{10pt}}
\typeout{===: \the\powerfactor{1.2}{3}{10pt}}
\typeout{===: \negpowerfactor{1.2}{3}{10pt}}
\typeout{===: \the\negpowerfactor{1.2}{3}{10pt}}

\begin{document}

{\fontsize{\powerfactor{1.2}{3}{10pt}}{\powerfactor{1.2}{3}{10pt}}\selectfont Hello TeXworld.\par}

{\fontsize{\negpowerfactor{1.2}{3}{10pt}}{\powerfactor{1.2}{3}{10pt}}\selectfont Hello TeXworld.\par}

\end{document}
David Carlisle
  • 757,742