Team Ai
Datasetpublic

Brunobkr/llama.cpp_AlgMor24_github

ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes3.1kdownloads
array.ts1137 linesDownload Raw Back to environments
1import {makeFragment, makeLineSpan, makeSpan, makeVList} from "../buildCommon";2import Style from "../Style";3import defineEnvironment from "../defineEnvironment";4import {parseCD} from "./cd";5import defineFunction from "../defineFunction";6import defineMacro from "../defineMacro";7import {MathNode} from "../mathMLTree";8import ParseError from "../ParseError";9import {assertNodeType, assertSymbolNodeType} from "../parseNode";10import {checkSymbolNodeType} from "../parseNode";11import {Token} from "../Token";12import {calculateSize, makeEm} from "../units";13 14import * as html from "../buildHTML";15import * as mml from "../buildMathML";16 17import type Parser from "../Parser";18import type {ParseNode, AnyParseNode} from "../parseNode";19import type {StyleStr, Mode} from "../types";20import type {HtmlBuilder, MathMLBuilder} from "../defineFunction";21import type {HtmlDomNode} from "../domTree";22 23type EnvContextLike = {24    parser: Parser;25    envName: string;26    mode: Mode;27};28 29// Data stored in the ParseNode associated with the environment.30export type AlignSpec = {type: "separator", separator: string} | {31    type: "align";32    align: string;33    pregap?: number;34    postgap?: number;35};36 37// Type to indicate column separation in MathML38export type ColSeparationType = "align" | "alignat" | "gather" | "small" | "CD";39 40// Helper functions41function getHLines(parser: Parser): boolean[] {42    // Return an array. The array length = number of hlines.43    // Each element in the array tells if the line is dashed.44    const hlineInfo = [];45    parser.consumeSpaces();46    let nxt = parser.fetch().text;47    if (nxt === "\\relax") { // \relax is an artifact of the \cr macro below48        parser.consume();49        parser.consumeSpaces();50        nxt = parser.fetch().text;51    }52    while (nxt === "\\hline" || nxt === "\\hdashline") {53        parser.consume();54        hlineInfo.push(nxt === "\\hdashline");55        parser.consumeSpaces();56        nxt = parser.fetch().text;57    }58    return hlineInfo;59}60 61const validateAmsEnvironmentContext = (context: EnvContextLike) => {62    const settings = context.parser.settings;63    if (!settings.displayMode) {64        throw new ParseError(`{${context.envName}} can be used only in` +65            ` display mode.`);66    }67};68 69const gatherEnvironments = new Set(["gather", "gather*"]);70 71// autoTag (an argument to parseArray) can be one of three values:72// * undefined: Regular (not-top-level) array; no tags on each row73// * true: Automatic equation numbering, overridable by \tag74// * false: Tags allowed on each row, but no automatic numbering75// This function *doesn't* work with the "split" environment name.76function getAutoTag(name: string): boolean | null | undefined {77    if (!name.includes("ed")) {78        return !name.includes("*");79    }80    // return undefined;81}82 83/**84 * Parse the body of the environment, with rows delimited by \\ and85 * columns delimited by &, and create a nested list in row-major order86 * with one group per cell.  If given an optional argument style87 * ("text", "display", etc.), then each cell is cast into that style.88 */89function parseArray(90    parser: Parser,91    {92        hskipBeforeAndAfter,93        addJot,94        cols,95        arraystretch,96        colSeparationType,97        autoTag,98        singleRow,99        emptySingleRow,100        maxNumCols,101        leqno,102    }: {103        hskipBeforeAndAfter?: boolean;104        addJot?: boolean;105        cols?: AlignSpec[];106        arraystretch?: number;107        colSeparationType?: ColSeparationType;108        autoTag?: boolean | null | undefined;109        singleRow?: boolean;110        emptySingleRow?: boolean;111        maxNumCols?: number;112        leqno?: boolean;113    },114    style: StyleStr,115): ParseNode<"array"> {116    parser.gullet.beginGroup();117    if (!singleRow) {118        // \cr is equivalent to \\ without the optional size argument (see below)119        // TODO: provide helpful error when \cr is used outside array environment120        parser.gullet.macros.set("\\cr", "\\\\\\relax");121    }122 123    // Get current arraystretch if it's not set by the environment124    if (!arraystretch) {125        const stretch = parser.gullet.expandMacroAsText("\\arraystretch");126        if (stretch == null) {127            // Default \arraystretch from lttab.dtx128            arraystretch = 1;129        } else {130            arraystretch = parseFloat(stretch);131            if (!arraystretch || arraystretch < 0) {132                throw new ParseError(`Invalid \\arraystretch: ${stretch}`);133            }134        }135    }136 137    // Start group for first cell138    parser.gullet.beginGroup();139 140    let row: AnyParseNode[] = [];141    const body: AnyParseNode[][] = [row];142    const rowGaps = [];143    const hLinesBeforeRow = [];144    const tags: Array<AnyParseNode[] | boolean> | undefined =145        (autoTag != null ? [] : undefined);146 147    // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent148    // whether this row should have an equation number.  Simulate this with149    // a \@eqnsw macro set to 1 or 0.150    function beginRow() {151        if (autoTag) {152            parser.gullet.macros.set("\\@eqnsw", "1", true);153        }154    }155    function endRow() {156        if (tags) {157            if (parser.gullet.macros.get("\\df@tag")) {158                tags.push(parser.subparse([new Token("\\df@tag")]));159                parser.gullet.macros.set("\\df@tag", undefined, true);160            } else {161                tags.push(Boolean(autoTag) &&162                    parser.gullet.macros.get("\\@eqnsw") === "1");163            }164        }165    }166    beginRow();167 168    // Test for \hline at the top of the array.169    hLinesBeforeRow.push(getHLines(parser));170 171    while (true) {172        // Parse each cell in its own group (namespace)173        const cellBody = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");174        parser.gullet.endGroup();175        parser.gullet.beginGroup();176        let cell: AnyParseNode = {177            type: "ordgroup",178            mode: parser.mode,179            body: cellBody,180        };181        if (style) {182            cell = {183                type: "styling",184                mode: parser.mode,185                style,186                resetFont: true,187                body: [cell],188            };189        }190        row.push(cell);191        const next = parser.fetch().text;192        if (next === "&") {193            if (maxNumCols && row.length === maxNumCols) {194                if (singleRow || colSeparationType) {195                    // {equation} or {split}196                    throw new ParseError("Too many tab characters: &",197                                        parser.nextToken);198                } else {199                    // {array} environment200                    parser.settings.reportNonstrict("textEnv", "Too few columns " +201                    "specified in the {array} column argument.");202                }203            }204            parser.consume();205        } else if (next === "\\end") {206            endRow();207            // Arrays terminate newlines with `\crcr` which consumes a `\cr` if208            // the last line is empty.  However, AMS environments keep the209            // empty row if it's the only one.210            // NOTE: Currently, `cell` is the last item added into `row`.211            if (row.length === 1 && cell.type === "styling" &&212                cell.body.length === 1 && cell.body[0].type === "ordgroup" &&213                cell.body[0].body.length === 0 &&214                (body.length > 1 || !emptySingleRow)) {215                body.pop();216            }217            if (hLinesBeforeRow.length < body.length + 1) {218                hLinesBeforeRow.push([]);219            }220            break;221        } else if (next === "\\\\") {222            parser.consume();223            let size;224            // \def\Let@{\let\\\math@cr}225            // \def\math@cr{...\math@cr@}226            // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}227            // \def\math@cr@@[#1]{...\math@cr@@@...}228            // \def\math@cr@@@{\cr}229            if (parser.gullet.future().text !== " ") {230                size = parser.parseSizeGroup(true);231            }232            rowGaps.push(size ? size.value : null);233            endRow();234 235            // check for \hline(s) following the row separator236            hLinesBeforeRow.push(getHLines(parser));237 238            row = [];239            body.push(row);240            beginRow();241        } else {242            throw new ParseError("Expected & or \\\\ or \\cr or \\end",243                                 parser.nextToken);244        }245    }246 247    // End cell group248    parser.gullet.endGroup();249    // End array group defining \cr250    parser.gullet.endGroup();251 252    return {253        type: "array",254        mode: parser.mode,255        addJot,256        arraystretch,257        body,258        cols,259        rowGaps,260        hskipBeforeAndAfter,261        hLinesBeforeRow,262        colSeparationType,263        tags,264        leqno,265    };266}267 268// Decides on a style for cells in an array according to whether the given269// environment name starts with the letter 'd'.270function dCellStyle(envName: string): StyleStr {271    if (envName.slice(0, 1) === "d") {272        return "display";273    } else {274        return "text";275    }276}277 278type Outrow = {279    cells: HtmlDomNode[];280    height: number;281    depth: number;282    pos: number;283};284 285const htmlBuilder: HtmlBuilder<"array"> = function(group, options) {286    let r;287    let c;288    const nr = group.body.length;289    const hLinesBeforeRow = group.hLinesBeforeRow;290    let nc = 0;291    const body: Outrow[] = new Array(nr);292    const hlines: Array<{pos: number; isDashed: boolean}> = [];293    const ruleThickness = Math.max(294        // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.295        options.fontMetrics().arrayRuleWidth,296        options.minRuleThickness, // User override.297    );298 299    // Horizontal spacing300    const pt = 1 / options.fontMetrics().ptPerEm;301    let arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls302    if (group.colSeparationType && group.colSeparationType === "small") {303        // We're in a {smallmatrix}. Default column space is \thickspace,304        // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.305        // But that needs adjustment because LaTeX applies \scriptstyle to the306        // entire array, including the colspace, but this function applies307        // \scriptstyle only inside each element.308        const localMultiplier = options.havingStyle(Style.SCRIPT).sizeMultiplier;309        arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);310    }311 312    // Vertical spacing313    const baselineskip = group.colSeparationType === "CD"314        ? calculateSize({number: 3, unit: "ex"}, options)315        : 12 * pt; // see size10.clo316    // Default \jot from ltmath.dtx317    // TODO(edemaine): allow overriding \jot via \setlength (#687)318    const jot = 3 * pt;319    const arrayskip = group.arraystretch * baselineskip;320    const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and321    const arstrutDepth = 0.3 * arrayskip;  // \@arstrutbox in lttab.dtx322 323    let totalHeight = 0;324 325    // Set a position for \hline(s) at the top of the array, if any.326    function setHLinePos(hlinesInGap: boolean[]) {327        for (let i = 0; i < hlinesInGap.length; ++i) {328            if (i > 0) {329                totalHeight += 0.25;330            }331            hlines.push({pos: totalHeight, isDashed: hlinesInGap[i]});332        }333    }334    setHLinePos(hLinesBeforeRow[0]);335 336    for (r = 0; r < group.body.length; ++r) {337        const inrow = group.body[r];338        let height = arstrutHeight; // \@array adds an \@arstrut339        let depth = arstrutDepth;   // to each tow (via the template)340 341        if (nc < inrow.length) {342            nc = inrow.length;343        }344 345        const outrow: Outrow = {346            cells: new Array<HtmlDomNode>(inrow.length),347            height: 0,348            depth: 0,349            pos: 0,350        };351        for (c = 0; c < inrow.length; ++c) {352            const elt = html.buildGroup(inrow[c], options);353            if (depth < elt.depth) {354                depth = elt.depth;355            }356            if (height < elt.height) {357                height = elt.height;358            }359            outrow.cells[c] = elt;360        }361 362        const rowGap = group.rowGaps[r];363        let gap = 0;364        if (rowGap) {365            gap = calculateSize(rowGap, options);366            if (gap > 0) { // \@argarraycr367                gap += arstrutDepth;368                if (depth < gap) {369                    depth = gap; // \@xargarraycr370                }371                gap = 0;372            }373        }374        // In AMS multiline environments such as aligned and gathered, rows375        // correspond to lines that have additional \jot added between lines376        // via \openup.377        // We simulate this by adding \jot depth to each row except the last.378        if (group.addJot && r < group.body.length - 1) {379            depth += jot;380        }381 382        outrow.height = height;383        outrow.depth = depth;384        totalHeight += height;385        outrow.pos = totalHeight;386        totalHeight += depth + gap; // \@yargarraycr387        body[r] = outrow;388 389        // Set a position for \hline(s), if any.390        setHLinePos(hLinesBeforeRow[r + 1]);391    }392 393    const offset = totalHeight / 2 + options.fontMetrics().axisHeight;394    const colDescriptions = group.cols || [];395    const cols: HtmlDomNode[] = [];396    let colSep;397    let colDescrNum;398    const tagSpans: Array<{399        type: "elem";400        elem: HtmlDomNode;401        shift: number;402    }> = [];403 404    if (group.tags && group.tags.some(tag => tag)) {405        // An environment with manual tags and/or automatic equation numbers.406        // Create node(s), the latter of which trigger CSS counter increment.407        for (r = 0; r < nr; ++r) {408            const rw = body[r];409            const shift = rw.pos - offset;410            const tag = group.tags[r];411            let tagSpan;412            if (tag === true) {  // automatic numbering413                tagSpan = makeSpan(["eqn-num"], [], options);414            } else if (tag === false) {415                // \nonumber/\notag or starred environment416                tagSpan = makeSpan([], [], options);417            } else {  // manual \tag418                tagSpan = makeSpan([],419                    html.buildExpression(tag, options, true), options);420            }421            tagSpan.depth = rw.depth;422            tagSpan.height = rw.height;423            tagSpans.push({type: "elem", elem: tagSpan, shift});424        }425    }426 427    for (c = 0, colDescrNum = 0;428         // Continue while either there are more columns or more column429         // descriptions, so trailing separators don't get lost.430         c < nc || colDescrNum < colDescriptions.length;431         ++c, ++colDescrNum) {432        let colDescr: AlignSpec | undefined = colDescriptions[colDescrNum];433 434        let firstSeparator = true;435        while (colDescr?.type === "separator") {436            // If there is more than one separator in a row, add a space437            // between them.438            if (!firstSeparator) {439                colSep = makeSpan(["arraycolsep"], []);440                colSep.style.width =441                    makeEm(options.fontMetrics().doubleRuleSep);442                cols.push(colSep);443            }444 445            if (colDescr.separator === "|" || colDescr.separator === ":") {446                const lineType = colDescr.separator === "|" ? "solid" : "dashed";447                const separator = makeSpan(["vertical-separator"], [], options);448                separator.style.height = makeEm(totalHeight);449                separator.style.borderRightWidth = makeEm(ruleThickness);450                separator.style.borderRightStyle = lineType;451                separator.style.margin = `0 ${makeEm(-ruleThickness / 2)}`;452                const shift = totalHeight - offset;453                if (shift) {454                    separator.style.verticalAlign = makeEm(-shift);455                }456 457                cols.push(separator);458            } else {459                throw new ParseError(460                    "Invalid separator type: " + colDescr.separator);461            }462 463            colDescrNum++;464            colDescr = colDescriptions[colDescrNum];465            firstSeparator = false;466        }467 468        if (c >= nc) {469            continue;470        }471 472        let sepwidth;473        if (c > 0 || group.hskipBeforeAndAfter) {474            sepwidth = colDescr?.pregap ?? arraycolsep;475            if (sepwidth !== 0) {476                colSep = makeSpan(["arraycolsep"], []);477                colSep.style.width = makeEm(sepwidth);478                cols.push(colSep);479            }480        }481 482        const colElems: Array<{483            type: "elem";484            elem: HtmlDomNode;485            shift: number;486        }> = [];487        for (r = 0; r < nr; ++r) {488            const row = body[r];489            const elem = row.cells[c];490            if (!elem) {491                continue;492            }493            const shift = row.pos - offset;494            elem.depth = row.depth;495            elem.height = row.height;496            colElems.push({type: "elem", elem: elem, shift: shift});497        }498 499        const colVList = makeVList({500            positionType: "individualShift",501            children: colElems,502        }, options);503        const colSpan = makeSpan(504            ["col-align-" + (colDescr?.align || "c")],505            [colVList],506        );507        cols.push(colSpan);508 509        if (c < nc - 1 || group.hskipBeforeAndAfter) {510            sepwidth = colDescr?.postgap ?? arraycolsep;511            if (sepwidth !== 0) {512                colSep = makeSpan(["arraycolsep"], []);513                colSep.style.width = makeEm(sepwidth);514                cols.push(colSep);515            }516        }517    }518 519    let tableBody: HtmlDomNode = makeSpan(["mtable"], cols);520 521    // Add \hline(s), if any.522    if (hlines.length > 0) {523        const line = makeLineSpan("hline", options, ruleThickness);524        const dashes = makeLineSpan("hdashline", options, ruleThickness);525        const vListElems = [{type: "elem" as const, elem: tableBody, shift: 0}];526        while (hlines.length > 0) {527            const hline = hlines.pop()!;528            const lineShift = hline.pos - offset;529            if (hline.isDashed) {530                vListElems.push({type: "elem" as const, elem: dashes, shift: lineShift});531            } else {532                vListElems.push({type: "elem" as const, elem: line, shift: lineShift});533            }534        }535 536        tableBody = makeVList({537            positionType: "individualShift",538            children: vListElems,539        }, options);540    }541 542    if (tagSpans.length === 0) {543        return makeSpan(["mord"], [tableBody], options);544    } else {545        const eqnNumCol = makeVList({546            positionType: "individualShift",547            children: tagSpans,548        }, options);549        const tagCol = makeSpan(["tag"], [eqnNumCol], options);550        return makeFragment([tableBody, tagCol]);551    }552};553 554const alignMap: Record<string, string> = {555    c: "center ",556    l: "left ",557    r: "right ",558};559 560const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {561    const tbl = [];562    const glue = new MathNode("mtd", [], ["mtr-glue"]);563    const tag = new MathNode("mtd", [], ["mml-eqn-num"]);564    for (let i = 0; i < group.body.length; i++) {565        const rw = group.body[i];566        const row = [];567        for (let j = 0; j < rw.length; j++) {568            row.push(new MathNode("mtd",569                [mml.buildGroup(rw[j], options)]));570        }571        if (group.tags && group.tags[i]) {572            row.unshift(glue);573            row.push(glue);574            if (group.leqno) {575                row.unshift(tag);576            } else {577                row.push(tag);578            }579        }580        tbl.push(new MathNode("mtr", row));581    }582    let table = new MathNode("mtable", tbl);583 584    // Set column alignment, row spacing, column spacing, and585    // array lines by setting attributes on the table element.586 587    // Set the row spacing. In MathML, we specify a gap distance.588    // We do not use rowGap[] because MathML automatically increases589    // cell height with the height/depth of the element content.590 591    // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.592    // We simulate this by adding (arraystretch - 1)em to the gap. This593    // does a reasonable job of adjusting arrays containing 1 em tall content.594 595    // The 0.16 and 0.09 values are found empirically. They produce an array596    // similar to LaTeX and in which content does not interfere with \hlines.597    const gap = (group.arraystretch === 0.5)598        ? 0.1  // {smallmatrix}, {subarray}599        : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);600    table.setAttribute("rowspacing", makeEm(gap));601 602    // MathML table lines go only between cells.603    // To place a line on an edge we'll use <menclose>, if necessary.604    let menclose = "";605    let align = "";606 607    if (group.cols && group.cols.length > 0) {608        // Find column alignment, column spacing, and  vertical lines.609        const cols = group.cols;610        let columnLines = "";611        let prevTypeWasAlign = false;612        let iStart = 0;613        let iEnd = cols.length;614 615        if (cols[0].type === "separator") {616            menclose += "top ";617            iStart = 1;618        }619        if (cols[cols.length - 1].type === "separator") {620            menclose += "bottom ";621            iEnd -= 1;622        }623 624        for (let i = iStart; i < iEnd; i++) {625            const col = cols[i];626            if (col.type === "align") {627                align += alignMap[col.align];628 629                if (prevTypeWasAlign) {630                    columnLines += "none ";631                }632                prevTypeWasAlign = true;633            } else if (col.type === "separator") {634                // MathML accepts only single lines between cells.635                // So we read only the first of consecutive separators.636                if (prevTypeWasAlign) {637                    columnLines += col.separator === "|" ? "solid " : "dashed ";638                    prevTypeWasAlign = false;639                }640            }641        }642 643        table.setAttribute("columnalign", align.trim());644 645        if (/[sd]/.test(columnLines)) {646            table.setAttribute("columnlines", columnLines.trim());647        }648    }649 650    // Set column spacing.651    if (group.colSeparationType === "align") {652        const cols = group.cols || [];653        let spacing = "";654        for (let i = 1; i < cols.length; i++) {655            spacing += i % 2 ? "0em " : "1em ";656        }657        table.setAttribute("columnspacing", spacing.trim());658    } else if (group.colSeparationType === "alignat" ||659        group.colSeparationType === "gather") {660        table.setAttribute("columnspacing", "0em");661    } else if (group.colSeparationType === "small") {662        table.setAttribute("columnspacing", "0.2778em");663    } else if (group.colSeparationType === "CD") {664        table.setAttribute("columnspacing", "0.5em");665    } else {666        table.setAttribute("columnspacing", "1em");667    }668 669    // Address \hline and \hdashline670    let rowLines = "";671    const hlines = group.hLinesBeforeRow;672 673    menclose += hlines[0].length > 0 ? "left " : "";674    menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";675 676    for (let i = 1; i < hlines.length - 1; i++) {677        rowLines += (hlines[i].length === 0)678          ? "none "679             // MathML accepts only a single line between rows. Read one element.680          : hlines[i][0] ? "dashed " : "solid ";681    }682    if (/[sd]/.test(rowLines)) {683        table.setAttribute("rowlines", rowLines.trim());684    }685 686    if (menclose !== "") {687        table = new MathNode("menclose", [table]);688        table.setAttribute("notation", menclose.trim());689    }690 691    if (group.arraystretch && group.arraystretch < 1) {692        // A small array. Wrap in scriptstyle so row gap is not too large.693        table = new MathNode("mstyle", [table]);694        table.setAttribute("scriptlevel", "1");695    }696 697    return table;698};699 700// Convenience function for align, align*, aligned, alignat, alignat*, alignedat.701const alignedHandler = function(context: EnvContextLike, args: AnyParseNode[]) {702    if (!context.envName.includes("ed")) {703        validateAmsEnvironmentContext(context);704    }705    const cols: AlignSpec[] = [];706    const separationType: ColSeparationType = context.envName.includes("at") ? "alignat" : "align";707    const isSplit = context.envName === "split";708    const res = parseArray(context.parser,709        {710            cols,711            addJot: true,712            autoTag: isSplit ? undefined : getAutoTag(context.envName),713            emptySingleRow: true,714            colSeparationType: separationType,715            maxNumCols: isSplit ? 2 : undefined,716            leqno: context.parser.settings.leqno,717        },718        "display"719    );720 721    // Determining number of columns.722    // 1. If the first argument is given, we use it as a number of columns,723    //    and makes sure that each row doesn't exceed that number.724    // 2. Otherwise, just count number of columns = maximum number725    //    of cells in each row ("aligned" mode -- isAligned will be true).726    //727    // At the same time, prepend empty group {} at beginning of every second728    // cell in each row (starting with second cell) so that operators become729    // binary.  This behavior is implemented in amsmath's \start@aligned.730    let numMaths = 0;731    let numCols = 0;732    const emptyGroup: ParseNode<"ordgroup"> = {733        type: "ordgroup",734        mode: context.mode,735        body: [],736    };737    if (args[0] && args[0].type === "ordgroup") {738        let arg0 = "";739        for (let i = 0; i < args[0].body.length; i++) {740            const textord = assertNodeType(args[0].body[i], "textord");741            arg0 += textord.text;742        }743        numMaths = Number(arg0);744        numCols = numMaths * 2;745    }746    const isAligned = !numCols;747    res.body.forEach(function(row) {748        for (let i = 1; i < row.length; i += 2) {749            // Modify ordgroup node within styling node750            const styling = assertNodeType(row[i], "styling");751            const ordgroup = assertNodeType(styling.body[0], "ordgroup");752            ordgroup.body.unshift(emptyGroup);753        }754        if (!isAligned) { // Case 1755            const curMaths = row.length / 2;756            if (numMaths < curMaths) {757                throw new ParseError(758                    "Too many math in a row: " +759                    `expected ${numMaths}, but got ${curMaths}`,760                    row[0]);761            }762        } else if (numCols < row.length) { // Case 2763            numCols = row.length;764        }765    });766 767    // Adjusting alignment.768    // In aligned mode, we add one \qquad between columns;769    // otherwise we add nothing.770    for (let i = 0; i < numCols; ++i) {771        let align = "r";772        let pregap = 0;773        if (i % 2 === 1) {774            align = "l";775        } else if (i > 0 && isAligned) { // "aligned" mode.776            pregap = 1; // add one \quad777        }778        cols[i] = {779            type: "align",780            align: align,781            pregap: pregap,782            postgap: 0,783        };784    }785    res.colSeparationType = isAligned ? "align" : "alignat";786    return res;787};788 789// Arrays are part of LaTeX, defined in lttab.dtx so its documentation790// is part of the source2e.pdf file of LaTeX2e source documentation.791// {darray} is an {array} environment where cells are set in \displaystyle,792// as defined in nccmath.sty.793defineEnvironment({794    type: "array",795    names: ["array", "darray"],796    props: {797        numArgs: 1,798    },799    handler(context, args) {800        // Since no types are specified above, the two possibilities are801        // - The argument is wrapped in {} or [], in which case Parser's802        //   parseGroup() returns an "ordgroup" wrapping some symbol node.803        // - The argument is a bare symbol node.804        const symNode = checkSymbolNodeType(args[0]);805        const colalign: AnyParseNode[] =806            symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;807        const cols: AlignSpec[] = colalign.map(function(nde) {808            const node = assertSymbolNodeType(nde);809            const ca = node.text;810            if ("lcr".includes(ca)) {811                return {812                    type: "align",813                    align: ca,814                };815            } else if (ca === "|") {816                return {817                    type: "separator",818                    separator: "|",819                };820            } else if (ca === ":") {821                return {822                    type: "separator",823                    separator: ":",824                };825            }826            throw new ParseError("Unknown column alignment: " + ca, nde);827        });828        const res: Parameters<typeof parseArray>[1] = {829            cols,830            hskipBeforeAndAfter: true, // \@preamble in lttab.dtx831            maxNumCols: cols.length,832        };833        return parseArray(context.parser, res, dCellStyle(context.envName));834    },835    htmlBuilder,836    mathmlBuilder,837});838 839// The matrix environments of amsmath builds on the array environment840// of LaTeX, which is discussed above.841// The mathtools package adds starred versions of the same environments.842// These have an optional argument to choose left|center|right justification.843defineEnvironment({844    type: "array",845    names: [846        "matrix",847        "pmatrix",848        "bmatrix",849        "Bmatrix",850        "vmatrix",851        "Vmatrix",852        "matrix*",853        "pmatrix*",854        "bmatrix*",855        "Bmatrix*",856        "vmatrix*",857        "Vmatrix*",858    ],859    props: {860        numArgs: 0,861    },862    handler(context) {863        const delimiters = {864            "matrix": null,865            "pmatrix": ["(", ")"],866            "bmatrix": ["[", "]"],867            "Bmatrix": ["\\{", "\\}"],868            "vmatrix": ["|", "|"],869            "Vmatrix": ["\\Vert", "\\Vert"],870        }[context.envName.replace("*", "")];871        // \hskip -\arraycolsep in amsmath872        let colAlign = "c";873        const payload: Parameters<typeof parseArray>[1] = {874            hskipBeforeAndAfter: false,875            cols: [{type: "align", align: colAlign}],876        };877        if (context.envName.charAt(context.envName.length - 1) === "*") {878            // It's one of the mathtools starred functions.879            // Parse the optional alignment argument.880            const parser = context.parser;881            parser.consumeSpaces();882            if (parser.fetch().text === "[") {883                parser.consume();884                parser.consumeSpaces();885                colAlign = parser.fetch().text;886                if (!"lcr".includes(colAlign)) {887                    throw new ParseError("Expected l or c or r", parser.nextToken);888                }889                parser.consume();890                parser.consumeSpaces();891                parser.expect("]");892                parser.consume();893                payload.cols = [{type: "align", align: colAlign}];894            }895        }896        const res: ParseNode<"array"> =897            parseArray(context.parser, payload, dCellStyle(context.envName));898        // Populate cols with the correct number of column alignment specs.899        const numCols = Math.max(0, ...res.body.map(row => row.length));900        res.cols = new Array(numCols).fill(901            {type: "align", align: colAlign}902        );903        return delimiters ? {904            type: "leftright",905            mode: context.mode,906            body: [res],907            left: delimiters[0],908            right: delimiters[1],909            rightColor: undefined, // \right uninfluenced by \color in array910        } : res;911    },912    htmlBuilder,913    mathmlBuilder,914});915 916defineEnvironment({917    type: "array",918    names: ["smallmatrix"],919    props: {920        numArgs: 0,921    },922    handler(context) {923        const payload: Parameters<typeof parseArray>[1] = {arraystretch: 0.5};924        const res = parseArray(context.parser, payload, "script");925        res.colSeparationType = "small";926        return res;927    },928    htmlBuilder,929    mathmlBuilder,930});931 932defineEnvironment({933    type: "array",934    names: ["subarray"],935    props: {936        numArgs: 1,937    },938    handler(context, args) {939        // Parsing of {subarray} is similar to {array}940        const symNode = checkSymbolNodeType(args[0]);941        const colalign: AnyParseNode[] =942            symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;943        const cols: AlignSpec[] = colalign.map(function(nde) {944            const node = assertSymbolNodeType(nde);945            const ca = node.text;946            // {subarray} only recognizes "l" & "c"947            if ("lc".includes(ca)) {948                return {949                    type: "align",950                    align: ca,951                };952            }953            throw new ParseError("Unknown column alignment: " + ca, nde);954        });955        if (cols.length > 1) {956            throw new ParseError("{subarray} can contain only one column");957        }958        const payload: Parameters<typeof parseArray>[1] = {959            cols,960            hskipBeforeAndAfter: false,961            arraystretch: 0.5,962        };963        const res = parseArray(context.parser, payload, "script");964        if (res.body.length > 0 &&  res.body[0].length > 1) {965            throw new ParseError("{subarray} can contain only one column");966        }967        return res;968    },969    htmlBuilder,970    mathmlBuilder,971});972 973// A cases environment (in amsmath.sty) is almost equivalent to974// \def\arraystretch{1.2}%975// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.976// {dcases} is a {cases} environment where cells are set in \displaystyle,977// as defined in mathtools.sty.978// {rcases} is another mathtools environment. It's brace is on the right side.979defineEnvironment({980    type: "array",981    names: [982        "cases",983        "dcases",984        "rcases",985        "drcases",986    ],987    props: {988        numArgs: 0,989    },990    handler(context) {991        const payload: Parameters<typeof parseArray>[1] = {992            arraystretch: 1.2,993            cols: [{994                type: "align",995                align: "l",996                pregap: 0,997                // TODO(kevinb) get the current style.998                // For now we use the metrics for TEXT style which is what we were999                // doing before.  Before attempting to get the current style we1000                // should look at TeX's behavior especially for \over and matrices.1001                postgap: 1.0, /* 1em quad */1002            }, {1003                type: "align",1004                align: "l",1005                pregap: 0,1006                postgap: 0,1007            }],1008        };1009        const res: ParseNode<"array"> =1010            parseArray(context.parser, payload, dCellStyle(context.envName));1011        return {1012            type: "leftright",1013            mode: context.mode,1014            body: [res],1015            left: context.envName.includes("r") ? "." : "\\{",1016            right: context.envName.includes("r") ? "\\}" : ".",1017            rightColor: undefined,1018        };1019    },1020    htmlBuilder,1021    mathmlBuilder,1022});1023 1024// In the align environment, one uses ampersands, &, to specify number of1025// columns in each row, and to locate spacing between each column.1026// align gets automatic numbering. align* and aligned do not.1027// The alignedat environment can be used in math mode.1028// Note that we assume \nomallineskiplimit to be zero,1029// so that \strut@ is the same as \strut.1030defineEnvironment({1031    type: "array",1032    names: ["align", "align*", "aligned", "split"],1033    props: {1034        numArgs: 0,1035    },1036    handler: alignedHandler,1037    htmlBuilder,1038    mathmlBuilder,1039});1040 1041// A gathered environment is like an array environment with one centered1042// column, but where rows are considered lines so get \jot line spacing1043// and contents are set in \displaystyle.1044defineEnvironment({1045    type: "array",1046    names: ["gathered", "gather", "gather*"],1047    props: {1048        numArgs: 0,1049    },1050    handler(context) {1051        if (gatherEnvironments.has(context.envName)) {1052            validateAmsEnvironmentContext(context);1053        }1054        const res: Parameters<typeof parseArray>[1] = {1055            cols: [{1056                type: "align",1057                align: "c",1058            }],1059            addJot: true,1060            colSeparationType: "gather",1061            autoTag: getAutoTag(context.envName),1062            emptySingleRow: true,1063            leqno: context.parser.settings.leqno,1064        };1065        return parseArray(context.parser, res, "display");1066    },1067    htmlBuilder,1068    mathmlBuilder,1069});1070 1071// alignat environment is like an align environment, but one must explicitly1072// specify maximum number of columns in each row, and can adjust spacing between1073// each columns.1074defineEnvironment({1075    type: "array",1076    names: ["alignat", "alignat*", "alignedat"],1077    props: {1078        numArgs: 1,1079    },1080    handler: alignedHandler,1081    htmlBuilder,1082    mathmlBuilder,1083});1084 1085defineEnvironment({1086    type: "array",1087    names: ["equation", "equation*"],1088    props: {1089        numArgs: 0,1090    },1091    handler(context) {1092        validateAmsEnvironmentContext(context);1093        const res: Parameters<typeof parseArray>[1] = {1094            autoTag: getAutoTag(context.envName),1095            emptySingleRow: true,1096            singleRow: true,1097            maxNumCols: 1,1098            leqno: context.parser.settings.leqno,1099        };1100        return parseArray(context.parser, res, "display");1101    },1102    htmlBuilder,1103    mathmlBuilder,1104});1105 1106defineEnvironment({1107    type: "array",1108    names: ["CD"],1109    props: {1110        numArgs: 0,1111    },1112    handler(context) {1113        validateAmsEnvironmentContext(context);1114        return parseCD(context.parser);1115    },1116    htmlBuilder,1117    mathmlBuilder,1118});1119 1120defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");1121defineMacro("\\notag", "\\nonumber");1122 1123// Catch \hline outside array environment1124defineFunction({1125    type: "text", // Doesn't matter what this is.1126    names: ["\\hline", "\\hdashline"],1127    props: {1128        numArgs: 0,1129        allowedInText: true,1130        allowedInMath: true,1131    },1132    handler(context, args) {1133        throw new ParseError(1134            `${context.funcName} valid only within array environment`);1135    },1136});1137 
Brunobkr/llama.cpp_AlgMor24_github · Team Ai