6

I'm trying to make macro to work in biblatex edition field. Logic is following:

  • if edition =1 there is suffix -li (1-li)
  • if edition>1 and if edition<21 there is prefix me- (me-15,me-20 ..etc)
  • if edition = 40,60,80,100,200,...1000 there is also prefix me-
  • in other cases suffix -e (31-e, 21-e, 129-e, 1010-e)

here is a code which works:

 \protected\def\mkbibmascord#1{%
 \ifnum #1=1 #1-li \else %
 \ifnum #1<21 %
\ifnum #1>1 me-#1 \fi \else %
\ifnum #1 = 40  me-#1 \else%
\ifnum #1 = 60  me-#1 \else%
\ifnum #1 = 80  me-#1 \else%
\ifnum #1 = 100 me-#1 \else %
\ifnum #1 = 200  me-#1 \else %
#1-e
\fi\fi\fi\fi\fi\fi\fi%
}%
\protected\def\mkbibordinal{\mkbibmascord}%
\protected\def\mkbibfemord{\mkbibmascord}%
\protected\def\mkbibneutord{\mkbibmascord}%

but how can i write general code/improve above code? (not only for 200), becouse let say for calendar there will be alot if/fi-s

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • There might be some streamlining, if all the possible cases possessed consecutive numbers. But since they do not, nested \ifnum branching is probably the best you can do. – Steven B. Segletes Aug 18 '15 at 15:10
  • you are right , but shortening a code can be possible something like break, and,==' (equality) commands orcase`(like \case{n}) switch :) .. Isearch 'math in tex' but search gives just how to write mathequations, not TeX aritmetic :)...I need to learn more :) – Levan Shoshiashvili Aug 18 '15 at 15:39
  • Are these ordinal numbers? In which language? Is there a reference for the rules? – Heiko Oberdiek Aug 18 '15 at 15:39
  • yes. Language is georgian.. here are examples..no general rule is given in English http://learn101.org/georgian_numbers.php http://mylanguages.org/georgian_numbers.php .. Actually i run little bit forward..I'm going to write Gregoriancalendar-to-Ald Georgian calendar transliator and will need TeX arithmetic a lot. – Levan Shoshiashvili Aug 18 '15 at 15:56
  • Can remove ifnum #1 >1 in above code...works also fine \ifnum #1<21 % me-#1 \else % – Levan Shoshiashvili Aug 18 '15 at 16:05
  • I also checked how it is made for english...I need to count houndreds..did not make it and wrote what is above – Levan Shoshiashvili Aug 18 '15 at 16:27

3 Answers3

5

Here's an implementation in expl3:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\cs_new:Nn \georgian_ordinal:n
 {
  \int_compare:nTF { 1 < #1 < 21 }
   { me\mbox{-}#1 }
   { \georgian_ordinal_aux:n { #1 } }
 }

\cs_new:Nn \georgian_ordinal_aux:n
 {
  \int_case:nnF { #1 }
   {
    {    1 }{ #1\mbox{-}li }
    {   40 }{ me\mbox{-}#1 }
    {   60 }{ me\mbox{-}#1 }
    {   80 }{ me\mbox{-}#1 }
    {  100 }{ me\mbox{-}#1 }
    {  200 }{ me\mbox{-}#1 }
    {  300 }{ me\mbox{-}#1 }
    {  400 }{ me\mbox{-}#1 }
    {  500 }{ me\mbox{-}#1 }
    {  600 }{ me\mbox{-}#1 }
    {  700 }{ me\mbox{-}#1 }
    {  800 }{ me\mbox{-}#1 }
    {  900 }{ me\mbox{-}#1 }
    { 1000 }{ me\mbox{-}#1 }
  }
  { #1\mbox{-}e }
 }

\cs_set_eq:NN \mkbibmascord  \georgian_ordinal:n
\cs_set_eq:NN \mkbibordinal  \georgian_ordinal:n
\cs_set_eq:NN \mkbibfemord   \georgian_ordinal:n
\cs_set_eq:NN \mkbibneutcord \georgian_ordinal:n

\ExplSyntaxOff

\begin{document}

% a loop for testing
\ExplSyntaxOn
\int_step_inline:nnnn { 1 } { 1 } { 1010 } { \mkbibmascord { #1 } ~ }
\ExplSyntaxOff

\end{document}

I only show the test between 1 and 210:

enter image description here

Maybe something more efficient can be done if the rules for numbers above 1000 are explained.

egreg
  • 1,121,712
4

The solution using \ifnums and using \variants{num}{list}{true-text}{false-text} macro which expands to the "true-text" if num is equal to the number in the list else it expands to the "false-text".

\def\variants#1#2{\variantsA{#1}#2,,\end}
\def\variantsA#1#2,{\ifx,#2,\expandafter\variantsE \else
   \ifnum#1=#2 \variantsC \else
      \expandafter\expandafter\expandafter\variantsA
   \fi\fi{#1}}
\def\variantsC#1\end#2#3{\fi\fi#2}
\def\variantsE#1\end#2#3{#3}

\protected\def\mkbibmascord#1{%
   \ifnum#1<1 #1-e\else
   \ifnum#1=1 #1-li\else
   \ifnum#1<21 me-#1\else
   \variants{#1}{40,60,80,100,200,300,400,500,600,700,800,900,1000}{me-#1}{#1-e}%
   \fi\fi\fi
}
wipet
  • 74,238
3

The question has two relatively independent aspects:

 1. how to organize gracefully a long list of `\ifnum..` clauses, 
 2. how to automatize over a list.

I won't delve much about the second part here, illustrated in the code below by the handling of 300, 400, .., 1000 via \xintApplyUnbraced from package xinttools. This is expandable. And the Test itself uses an \xintFor loop (non-expandable). For example wipet's answer has one-line macros sufficient here. By laziness I used the loops from xinttools.

My answer is mainly the observation that very simple macros:

\long\def\DoThis #1#2\OrThat #3{\fi #1}
\long\def\OrThat #1{#1}

can be used to handle point 1. No more \fi\fi\fi\fi...\fi. And expandability is maintained.

\long\def\DoThis #1#2\OrThat #3{\fi #1}
\long\def\OrThat #1{#1}

% for the (optional) list manipulations in the code and in the Test
\input xinttools.sty

% Notice that this \georgianordinal is an expandable macro
\def\georgianordinal #1{%
   \ifnum #1=1  \DoThis{1-li}\fi
   \ifnum #1<21 \DoThis{me-#1}\fi
   \ifnum #1=40 \DoThis{me-#1}\fi
   \ifnum #1=60 \DoThis{me-#1}\fi
   \ifnum #1=80 \DoThis{me-#1}\fi
   \ifnum #1=100 \DoThis{me-#1}\fi
   \ifnum #1=200 \DoThis{me-#1}\fi
   \xintApplyUnbraced
        {\georgianordinalaux {#1}}
        {{300}{400}{500}{600}{700}{800}{900}{1000}}%
   \OrThat {#1-e}%
}

% notice the space before \ifnum, which is there to stop 
% an expansion done via \romannumeral-`0 by \xintApplyUnbraced
\def\georgianordinalaux #1#2{ \ifnum #1=#2 \DoThis{me-#1}\fi}

% Test:

\xintFor #1 in {\xintintegers} \do {%
     \georgianordinal {\the#1},
     \ifnum#1>1050 \expandafter\xintBreakFor\fi
}

\bye

enter image description here