2

I have come upon a problem I'd like to solve but unable to by myself. My intention is to create a library of components with different parameters and do calculations with FPeval. Here is the code:

\documentclass{article}
\usepackage{fp}% http://ctan.org/pkg/fp
\usepackage{xstring}% http://ctan.org/pkg/xstring
\usepackage{xparse}% http://ctan.org/pkg/xparse
\usepackage{color}

%STRUCT
\newcommand \Rmin[2]{\ensuremath{\FPeval{\result}{round(#1-(#1*#2/100),2)}\result}}
\newcommand \Rmax[2]{\ensuremath{\FPeval{\result}{round(#1+(#1*#2/100),2)}\result}}

\newcommand\defResCMtype[2]{%defined VARIOUS types
    \expandafter\newcommand\csname TOL#1\endcsname{#2}
}
\newcommand\defResCM[3]{%
    \expandafter\newcommand\csname value#1\endcsname{#2}
    \expandafter\newcommand\csname #1min\endcsname{
        \StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
        \IfEqCase{\tmp}{{typeX}{\Rmin{#2}{\TOLtypeX}}
        }%
        [{\color{red}XXXXXX}] %ERROR
    }
    \expandafter\newcommand\csname #1max\endcsname{
        \StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
        \IfEqCase{\tmp}{{typeX}{\Rmax{#2}{\TOLtypeX}}
        }%
        [{\color{red}XXXXXX}] %ERROR
    }
}

%LIB
\defResCMtype{typeX}{5}

\defResCM{compX}{100}{typeX}

%CALC
\newcommand \calc[2]{\ensuremath{\FPeval{\result}{round(#1,#2)}\result}}

\newcommand \testcalcA{\ensuremath{\calc{(105 / 95)}{2}}} %calculated with numbers
\newcommand \testcalcB{\ensuremath{\calc{((\compXmax)/(\compXmin))}{2}}} %calculated with macros -> NOT WORKING


\begin{document}

test = \valuecompX \\
test2= \compXmax \\
test3= \compXmin \\

A = \testcalcA \\ %-> WORKING
%B = \testcalcB \\ %-> NOT WORKING

\end{document}

If I manually enter the numbers created from the test2 & test3 then FPeval calculates the equation A, however, if I want to pass these values automatically as (\compXmax) & (\compXmin) or even comXmax & comXmin in

\newcommand \testcalcB{\ensuremath{\calc{((\compXmax)/(\compXmin))}{2}}}

I get an error ! Use of \@newline doesn't match its definition.\kernel@ifnextchar ...rved@d =#1\def \reserved@a {#2}\def \reserved@b {#3}\f... B = \testcalcB.

Manually inserting numbers between calculations in a document is error prone which I would very much like to avoid, since updating a parameter directly in library would need an update to the whole document where these parameters are used.

Paul Gessler
  • 29,607
MAAG
  • 67
  • 1
    As it stands you are not actually assigning numbers to \compXmax and \compXmin, and your string operations are not expandable. Can you explain what the above implements so we can avoid having to work that out and can make useful code suggestions? – Joseph Wright Jan 09 '15 at 08:58
  • Thank you for a kind welcome Mr. @Hupfer. The idea of above code is to build a library with components such as \defResCM{compX}{100}{typeX}, set its value and divide it by type. From these parameters calculate the minimum, maximum value and use these in other equations. Therefore avoid re-typing minmax values which is rather error prone when there are hundreads or more components used. That is why I would like to have a separate file with stored components. Tried the code below from @Steven B. Segletes and it works, but I'm not fond of a library in the document. – MAAG Jan 09 '15 at 13:05
  • @MAAG If you prefer the library in the preamble, I will revise. I did it because an error in the library printed out text, which cannot happen in the preamble. – Steven B. Segletes Jan 09 '15 at 19:29
  • @StevenB.Segletes That would be very appreciated. Thank you. – MAAG Jan 11 '15 at 17:56
  • @MAAG In the preamble, using my answer, you can say \AtBeginDocument{\defResCMtype{typeX}{5}\defResCM{compX}{100}{typeX}}, which works fine with the present construct. – Steven B. Segletes Jan 12 '15 at 03:09
  • Please see revision. – Steven B. Segletes Jan 12 '15 at 03:26

1 Answers1

2

The key is you want \compXmin and \compXmax to be evaluated already at their assignment, without the actual calculation embedded in their definitions.

EDITED to allow library to be set in the preamble (which was mentioned in a comment of the OP), through the use of \AtBeginDocument{}. RE-EDITED to save intermediate calculations (\testcalcB result saved in \thetestcalcB, \testcalcC result saved in \thetestcalcC).

\documentclass{article}
\usepackage{fp}% http://ctan.org/pkg/fp
\usepackage{xstring}% http://ctan.org/pkg/xstring
\usepackage{xparse}% http://ctan.org/pkg/xparse
\usepackage{xcolor}

%STRUCT
\newcommand \Rmin[2]{\ensuremath{\FPeval{\result}{round(#1-(#1*#2/100),2)}%
  \xdef\theRmin{\result}}}
\newcommand \Rmax[2]{\ensuremath{\FPeval{\result}{round(#1+(#1*#2/100),2)}%
  \xdef\theRmax{\result}}}

\newcommand\defResCMtype[2]{%defined VARIOUS types
    \expandafter\def\csname TOL#1\endcsname{#2}%
\ignorespaces}
\newcommand\defResCM[3]{%
    \expandafter\def\csname value#1\endcsname{#2}%
        \StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
        \IfEqCase{\tmp}{{typeX}{\Rmin{#2}{\TOLtypeX}\Rmax{#2}{\TOLtypeX}%
                                \expandafter\xdef\csname #1max\endcsname{\theRmax}%
                                \expandafter\xdef\csname #1min\endcsname{\theRmin}%
                               }%
                       }%
        [{\unskip\textcolor{red}{ERROR DEFINING: #1}\par}] %ERROR
\ignorespaces}
%LIB
\AtBeginDocument{
\defResCMtype{typeX}{5}
\defResCM{compX}{100}{typeX}
\defResCMtype{typeX}{10}
\defResCM{altX}{150}{typeX}
\defResCM{compY}{200}{type Y}
}
%CALC
\newcommand \calc[2]{\ensuremath{\FPeval{\result}{round(#1,#2)}}%
                     \xdef\thecalc{\result}}

\newcommand \testcalcB[1]{\ensuremath{\calc{((\csname#1max\endcsname)/%
                          (\csname#1min\endcsname))}{2}}%
                          \edef\thetestcalcB{\thecalc}\thetestcalcB}

\newcommand \testcalcC[1] {\ensuremath{\calc{(\thetestcalcB * \csname#1min\endcsname)}%
                          {2}}\edef\thetestcalcC{\thecalc}\thetestcalcC}
\begin{document}
test = \valuecompX \par
test2= \compXmax \par
test3= \compXmin \par
\medskip
B = \testcalcB{compX} \par %-> NOW WORKING
C = \testcalcC{compX} \par %-> NOW WORKING
\medskip
test = \valuealtX \par
test2= \altXmax \par
test3= \altXmin \par
\medskip
B = \testcalcB{altX} \par %-> NOW WORKING
C = \testcalcC{altX} \par %-> NOW WORKING
\end{document}

enter image description here

  • Great, it works, thank you. Is there also a possibility that this combination would work with reusing this\newcommand \testcalcB{{\calc{(compXmax * compXmin)}{2}}} in this again \newcommand \testcalcC{{\calc{(testcalcB * compXmin)}{2}}}? – MAAG Jan 12 '15 at 08:12
  • @MAAG Done. I hope this serves your need. – Steven B. Segletes Jan 12 '15 at 11:24