\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{malagasy-numberwords}[2026/09/05 v0.1.0 Nombres cardinaux malgaches] %% %% This work may be distributed and/or modified under the conditions of %% the LaTeX Project Public License, either version 1.3c of this license %% or (at your option) any later version. The latest version of this %% license is in: https://www.latex-project.org/lppl.txt %% This work has the LPPL maintenance status 'maintained'. %% The Current Maintainer of this work is the malagasy-numberwords %% contributors (RALAHADY Bruno Bakys, TOTOHASINA André). %% This work consists of the files malagasy-numberwords.sty and %% fc-malagasy-numberwords.def. %% % Port LaTeX (e-TeX/\numexpr, macros classiques) de la grammaire cardinale validee % dans le paquet Python malagasy-numberwords (formal-grammar.md, regles R1-R8, R7'). % Portee : 0 <= n <= 2147483647 environ (limite des compteurs TeX 32 bits -- NOTE : % plus restrictif que cardinal.py, qui n'a pas cette limite ; voir README de ce % dossier). Separation donnees/moteur : tables lexicales en tete de fichier. % --------------------------------------------------------------------------- % Donnees linguistiques (cf. rules/mutation.py) % --------------------------------------------------------------------------- \newcommand{\mnw@setword}[3]{\expandafter\def\csname mnw@#1@#2\endcsname{#3}} \mnw@setword{unit}{1}{iray} \mnw@setword{unit}{2}{roa} \mnw@setword{unit}{3}{telo} \mnw@setword{unit}{4}{efatra} \mnw@setword{unit}{5}{dimy} \mnw@setword{unit}{6}{enina} \mnw@setword{unit}{7}{fito} \mnw@setword{unit}{8}{valo} \mnw@setword{unit}{9}{sivy} \mnw@setword{tens}{1}{folo} \mnw@setword{tens}{2}{roapolo} \mnw@setword{tens}{3}{telopolo} \mnw@setword{tens}{4}{efapolo} \mnw@setword{tens}{5}{dimampolo} \mnw@setword{tens}{6}{enimpolo} \mnw@setword{tens}{7}{fitopolo} \mnw@setword{tens}{8}{valopolo} \mnw@setword{tens}{9}{sivifolo} \mnw@setword{hundreds}{1}{zato} \mnw@setword{hundreds}{2}{roanjato} \mnw@setword{hundreds}{3}{telonjato} \mnw@setword{hundreds}{4}{efajato} \mnw@setword{hundreds}{5}{dimanjato} \mnw@setword{hundreds}{6}{eninjato} \mnw@setword{hundreds}{7}{fitonjato} \mnw@setword{hundreds}{8}{valonjato} \mnw@setword{hundreds}{9}{sivinjato} \newcommand{\mnw@unit}[1]{\csname mnw@unit@#1\endcsname} \newcommand{\mnw@unitcompound}[1]{\ifnum#1=1 iraika\else\mnw@unit{#1}\fi} \newcommand{\mnw@tens}[1]{\csname mnw@tens@#1\endcsname} \newcommand{\mnw@hundreds}[1]{\csname mnw@hundreds@#1\endcsname} % --------------------------------------------------------------------------- % Registres de travail % --------------------------------------------------------------------------- \newcount\mnw@du % chiffre des unites \newcount\mnw@dt % chiffre des dizaines \newcount\mnw@dh % chiffre des centaines \newcount\mnw@dm % chiffre des milliers \newcount\mnw@dy % chiffre des myriades (dizaines de mille) \newcount\mnw@dl % chiffre des centaines de mille (lakh) \newcount\mnw@divA \newcount\mnw@divB \newcount\mnw@divC \newcount\mnw@divD \newcount\mnw@divE \newcount\mnw@divF \newcommand{\mnw@setdigits}[1]{% % ATTENTION : \numexpr arrondit la division au plus proche (pas de troncature) -- % on utilise donc \divide sur des \count, qui tronque, comme le veut une % division entiere classique. \mnw@divA=#1\relax \divide\mnw@divA by 10\relax \mnw@divB=#1\relax \divide\mnw@divB by 100\relax \mnw@divC=#1\relax \divide\mnw@divC by 1000\relax \mnw@divD=#1\relax \divide\mnw@divD by 10000\relax \mnw@divE=#1\relax \divide\mnw@divE by 100000\relax \mnw@divF=#1\relax \divide\mnw@divF by 1000000\relax \mnw@du=\numexpr (#1)-\mnw@divA*10 \relax \mnw@dt=\numexpr \mnw@divA-\mnw@divB*10 \relax \mnw@dh=\numexpr \mnw@divB-\mnw@divC*10 \relax \mnw@dm=\numexpr \mnw@divC-\mnw@divD*10 \relax \mnw@dy=\numexpr \mnw@divD-\mnw@divE*10 \relax \mnw@dl=\numexpr \mnw@divE-\mnw@divF*10 \relax } % --------------------------------------------------------------------------- % R5 : bloc bas (unites, dizaines, centaines) -- construit dans \mnw@blocklow % --------------------------------------------------------------------------- \newcommand{\mnw@blocklow}{} \newcommand{\mnw@computeblocklow}{% \def\mnw@prefix{}% p0 (+eventuellement p1), avant jonction avec p2 \ifnum\mnw@du>0 \ifnum\mnw@dt>0 \ifnum\mnw@dt=1 \edef\mnw@prefix{\mnw@unitcompound{\the\mnw@du}\space ambin'ny\space\mnw@tens{\the\mnw@dt}}% \else \edef\mnw@prefix{\mnw@unitcompound{\the\mnw@du}\space amby\space\mnw@tens{\the\mnw@dt}}% \fi \else \edef\mnw@prefix{\mnw@unitcompound{\the\mnw@du}}% \fi \else \ifnum\mnw@dt>0 \edef\mnw@prefix{\mnw@tens{\the\mnw@dt}}% \fi \fi \ifnum\mnw@dh>0 \ifx\mnw@prefix\@empty \edef\mnw@blocklow{\mnw@hundreds{\the\mnw@dh}}% \else \ifnum\mnw@dh=1 \edef\mnw@blocklow{\mnw@prefix\space amby\space\mnw@hundreds{\the\mnw@dh}}% \else \edef\mnw@blocklow{\mnw@prefix\space sy\space\mnw@hundreds{\the\mnw@dh}}% \fi \fi \else \let\mnw@blocklow\mnw@prefix \fi } % --------------------------------------------------------------------------- % R6/R8 : terme d'echelle (arivo/alina/hetsy). #1=chiffre #2=mot #3=1 si forme % nue pour d=1 (arivo/zato), 0 sinon (alina/hetsy exigent "iray"). Resultat % dans \mnw@scaleterm (vide si #1=0). % --------------------------------------------------------------------------- \newcommand{\mnw@scaleterm}[3]{% \ifnum#1=0 \let\mnw@scaleterm@out\@empty \else \ifnum#1=1 \if1#3 \edef\mnw@scaleterm@out{#2}% \else \edef\mnw@scaleterm@out{iray\space#2}% \fi \else \edef\mnw@scaleterm@out{\mnw@unit{#1}\space#2}% \fi \fi } % Concatene jusqu'a 4 parties (deja calculees, eventuellement vides) avec "sy" \newcommand{\mnw@joinsy}[4]{% \def\mnw@acc{}% \renewcommand{\mnw@joinone}[1]{% \ifx##1\@empty\else \ifx\mnw@acc\@empty \edef\mnw@acc{##1}\else\edef\mnw@acc{\mnw@acc\space sy\space##1}\fi \fi }% \mnw@joinone{#1}\mnw@joinone{#2}\mnw@joinone{#3}\mnw@joinone{#4}% } \newcommand{\mnw@joinone}[1]{} % --------------------------------------------------------------------------- % below_tapitrisa : 0 <= n <= 999999, sans terme "tapitrisa". Resultat dans % \mnw@belowtap. % --------------------------------------------------------------------------- \newcommand{\mnw@belowtapitrisa}[1]{% \ifnum#1=0 \let\mnw@belowtap\@empty \else \mnw@setdigits{#1}% \mnw@computeblocklow \mnw@scaleterm{\the\mnw@dm}{arivo}{1}% \let\mnw@scaleA\mnw@scaleterm@out \mnw@scaleterm{\the\mnw@dy}{alina}{0}% \let\mnw@scaleB\mnw@scaleterm@out \mnw@scaleterm{\the\mnw@dl}{hetsy}{0}% \let\mnw@scaleC\mnw@scaleterm@out \mnw@joinsy{\mnw@blocklow}{\mnw@scaleA}{\mnw@scaleB}{\mnw@scaleC}% \let\mnw@belowtap\mnw@acc \fi } % --------------------------------------------------------------------------- % R7' : nombre complet, cycle recursif au-dela de tapitrisa. Resultat dans % \mnw@fullresult. NOTE : #1 doit tenir dans un compteur TeX (< 2^31 environ) -- % c'est une limite d'IMPLEMENTATION (pas linguistique), plus restrictive que % cardinal.py (entiers Python illimites). Voir README de ce dossier. % --------------------------------------------------------------------------- \newcount\mnw@topn \newcount\mnw@topm \newcount\mnw@topr \newcommand{\mnw@fullnumber}[1]{% \mnw@topn=#1\relax \ifnum\mnw@topn=0 \def\mnw@fullresult{aotra}% \else \mnw@topm=\mnw@topn\relax \divide\mnw@topm by 1000000\relax \mnw@topr=\numexpr\mnw@topn-\mnw@topm*1000000\relax \mnw@belowtapitrisa{\the\mnw@topm}% \let\mnw@mresult\mnw@belowtap \mnw@belowtapitrisa{\the\mnw@topr}% \let\mnw@rresult\mnw@belowtap \ifx\mnw@mresult\@empty \let\mnw@fullresult\mnw@rresult \else \ifnum\mnw@topm=1 \def\mnw@tapterm{iray\space tapitrisa}% \else \edef\mnw@tapterm{\mnw@mresult\space tapitrisa}% \fi \ifx\mnw@rresult\@empty \let\mnw@fullresult\mnw@tapterm \else \edef\mnw@fullresult{\mnw@rresult\space sy\space\mnw@tapterm}% \fi \fi \fi } % --------------------------------------------------------------------------- % Garde-fou : les compteurs TeX sont limites a environ +-2^31 (~2 147 483 647). % Plutot que de laisser TeX echouer avec un message cryptique ("Number too big") % pour un nombre plus grand, on detecte les cas manifestement hors de portee via % un comptage de caracteres (fiable sans avoir a parser le nombre comme entier) % et on emet une erreur de paquet explicite. % --------------------------------------------------------------------------- \newcount\mnw@strlen \newcommand{\mnw@strlenloop}[1]{% \ifx#1\@nil\else \advance\mnw@strlen by 1 \expandafter\mnw@strlenloop \fi } \newcommand{\mnw@checkrange}[1]{% \mnw@strlen=0 \expandafter\mnw@strlenloop#1\@nil \ifnum\mnw@strlen>10 \PackageError{malagasy-numberwords} {Nombre trop grand (#1) pour les compteurs TeX natifs (limite ~2^31)} {Ce port LaTeX ne peut pas depasser environ 2 147 483 647 : c'est une limite d'implementation des compteurs TeX, pas une limite linguistique (voir cardinal.py, qui n'a pas cette contrainte). Utilisez le paquet Python malagasy-numberwords pour ce nombre.}% \fi } % --------------------------------------------------------------------------- % Interface publique % --------------------------------------------------------------------------- \newcommand{\MalagasyNumberToWords}[1]{\mnw@checkrange{#1}\mnw@fullnumber{#1}\mnw@fullresult} % --------------------------------------------------------------------------- % Pourcentage (R-CUR-like : [cardinal] isan-jato, cf. percentage.py) % --------------------------------------------------------------------------- \newcommand{\MalagasyPercentageToWords}[1]{% \mnw@checkrange{#1}% \mnw@fullnumber{#1}% \edef\mnw@percentageresult{\mnw@fullresult\space isan-jato}% \mnw@percentageresult } % --------------------------------------------------------------------------- % Monnaie (seul MGA/ariary est sourcé, cf. currency.py et currency-model.md) % --------------------------------------------------------------------------- \newcommand{\MalagasyCurrencyToWords}[1]{% \mnw@checkrange{#1}% \mnw@fullnumber{#1}% \edef\mnw@currencyresult{\mnw@fullresult\space ariary}% \mnw@currencyresult } % --------------------------------------------------------------------------- % Decimal ([entier] faingo [decimale], cf. decimal.py et decimal-model.md). % #1 = partie entiere, #2 = partie decimale (sans le zero non significatif % -- limite connue, identique a decimal.py). % --------------------------------------------------------------------------- \newcommand{\MalagasyDecimalToWords}[2]{% \mnw@checkrange{#1}% \mnw@fullnumber{#1}% \edef\mnw@decimal@int{\mnw@fullresult}% \mnw@checkrange{#2}% \mnw@fullnumber{#2}% \edef\mnw@decimalresult{\mnw@decimal@int\space faingo\space\mnw@fullresult}% \mnw@decimalresult } % --------------------------------------------------------------------------- % Ordinal (voalohany=1er ; faha- + cardinal sinon, avec fusion+elision R-ORD3 % SEULEMENT si le cardinal est un seul mot, sinon faha reste separe -- R-ORD5, % cf. ordinal.py et ordinal-model.md). % --------------------------------------------------------------------------- \def\mnw@dosplit#1 #2\mnw@splitend{% \def\mnw@firstword@out{#1}% \def\mnw@restword@out{#2}% } \newcommand{\mnw@splitfirstword}[1]{\expandafter\mnw@dosplit#1 \mnw@splitend} \def\mnw@extractfirstchar#1#2\mnw@nilend{\def\mnw@firstchar@out{#1}} \def\mnw@lettere{e} \newcommand{\mnw@ordinal}[1]{% \ifnum#1=1 \def\mnw@ordinalresult{voalohany}% \else \mnw@checkrange{#1}% \mnw@fullnumber{#1}% \edef\mnw@ord@cardinal{\mnw@fullresult}% \mnw@splitfirstword{\mnw@ord@cardinal}% \ifx\mnw@restword@out\@empty \expandafter\mnw@extractfirstchar\mnw@firstword@out e\mnw@nilend \ifx\mnw@firstchar@out\mnw@lettere \edef\mnw@ordinalresult{fah\mnw@firstword@out}% \else \edef\mnw@ordinalresult{faha\mnw@firstword@out}% \fi \else \edef\mnw@ordinalresult{faha\space\mnw@ord@cardinal}% \fi \fi } \newcommand{\MalagasyOrdinalToWords}[1]{\mnw@ordinal{#1}\mnw@ordinalresult} % --------------------------------------------------------------------------- % Date ([jour ordinal] ny volana [mois] [annee], cf. date.py et date-model.md). % Meme mise en garde : seule la structure est confirmee, jour/annee epeles % restent des extrapolations. % --------------------------------------------------------------------------- \mnw@setword{month}{1}{Janoary} \mnw@setword{month}{2}{Febroary} \mnw@setword{month}{3}{Martsa} \mnw@setword{month}{4}{Aprily} \mnw@setword{month}{5}{Mey} \mnw@setword{month}{6}{Jona} \mnw@setword{month}{7}{Jolay} \mnw@setword{month}{8}{Aogositra} \mnw@setword{month}{9}{Septambra} \mnw@setword{month}{10}{Oktobra} \mnw@setword{month}{11}{Novambra} \mnw@setword{month}{12}{Desambra} \newcommand{\mnw@month}[1]{\csname mnw@month@#1\endcsname} \newcommand{\MalagasyDateToWords}[3]{% % #1 = jour, #2 = mois (1-12), #3 = annee \ifcase#2\relax \PackageError{malagasy-numberwords}{Mois invalide (0)}{Le mois doit etre entre 1 et 12.}% \or\edef\mnw@date@month{\mnw@month{1}}% \or\edef\mnw@date@month{\mnw@month{2}}% \or\edef\mnw@date@month{\mnw@month{3}}% \or\edef\mnw@date@month{\mnw@month{4}}% \or\edef\mnw@date@month{\mnw@month{5}}% \or\edef\mnw@date@month{\mnw@month{6}}% \or\edef\mnw@date@month{\mnw@month{7}}% \or\edef\mnw@date@month{\mnw@month{8}}% \or\edef\mnw@date@month{\mnw@month{9}}% \or\edef\mnw@date@month{\mnw@month{10}}% \or\edef\mnw@date@month{\mnw@month{11}}% \or\edef\mnw@date@month{\mnw@month{12}}% \else \PackageError{malagasy-numberwords}{Mois invalide (#2)}{Le mois doit etre entre 1 et 12.}% \fi \mnw@ordinal{#1}% \let\mnw@date@day\mnw@ordinalresult \mnw@checkrange{#3}% \mnw@fullnumber{#3}% \edef\mnw@dateresult{\mnw@date@day\space ny\space volana\space\mnw@date@month\space\mnw@fullresult}% \mnw@dateresult } % --------------------------------------------------------------------------- % Chargement de la couche fmtcount. Le fichier d'interoperabilite est nomme % "fc-malagasy-numberwords.def" (et non "fc-malagasy.def") pour rester % facilement identifiable comme appartenant a ce paquet dans l'ensemble de % l'archive CTAN/TeX Live -- mais cela signifie que la commande standard de % fmtcount, "\FCloadlang{malagasy}", qui cherche exclusivement un fichier % nomme "fc-.def", NE TROUVE PAS ce fichier. Cette macro reproduit % l'essentiel du mecanisme interne de \FCloadlang (fmtcount.sty) en ciblant % le nom de fichier reellement utilise par ce paquet. \newcommand{\MalagasyLoadFmtcountSupport}{% \makeatletter \@ifpackageloaded{fmtcount}{% \@set@mulitling@fmtcount \def\languagename{malagasy}% \InputIfFileExists{fc-malagasy-numberwords.def}% {% \ifdefempty{\fc@languages}% {\gdef\fc@languages{malagasy}}% {\gappto\fc@languages{,malagasy}}% \gdef\fc@mainlang{malagasy}% }% {\PackageError{malagasy-numberwords}{fc-malagasy-numberwords.def not found}% {Make sure fc-malagasy-numberwords.def is on TeX's search path.}}% }{% \PackageError{malagasy-numberwords}{fmtcount is not loaded}% {Load \string\usepackage{fmtcount} before \string\MalagasyLoadFmtcountSupport.}% }% \makeatother }