{
  "category": "Statistical functions",
  "display_name": "TREND",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.TREND",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20131"
      ],
      "larger_numeric": 0,
      "last_bit": 2,
      "matched": 10,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 12,
      "unread": 0,
      "worst_ulp": 2
    },
    "detail": "Everything else matches (12 in the answer bank and 199 workbook cells). Last-bit means a finite number within 16 ULP of Excel's.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "close",
    "state_label": "Close: last-bit deviations remain",
    "summary": "Close: 2 of 211 recorded answers differ in the last bits, worst 2 ULP",
    "workbook_corpus": {
      "cells": 199,
      "matched": 199
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L424-L426",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/regression_forecast_family.rs#L791-L797",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/regression_forecast_family.rs#L818-L823",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/regression_forecast_family.rs#L913-L927",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/ported/regression_forecast_family.rs#L1158-L1177"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/statistics::regression",
        "ported/excel_numeric::binary_with",
        "ported/excel_numeric::excel_x87_add",
        "ported/excel_numeric::excel_x87_sub",
        "ported/excel_numeric::excel_x87_mul",
        "ported/excel_numeric::excel_x87_div",
        "ported/excel_numeric/x87::mul",
        "ported/excel_numeric/x87::add",
        "ported/excel_numeric/x87::sub",
        "ported/excel_numeric/x87::div",
        "ported/regression_forecast_family::GramInterval::checked",
        "ported/regression_forecast_family::GramInterval::subtract",
        "ported/regression_forecast_family::GramInterval::multiply",
        "ported/regression_forecast_family::GramInterval::square",
        "ported/regression_forecast_family::GramInterval::divide_positive",
        "ported/regression_forecast_family::moment",
        "ported/regression_forecast_family::column",
        "ported/regression_forecast_family::entry",
        "ported/regression_forecast_family::factor_column",
        "ported/regression_forecast_family::unresolved_inner",
        "ported/regression_forecast_family::unresolved",
        "ported/regression_forecast_family::resolve_arg_eval",
        "ported/regression_forecast_family::optional_arg_value",
        "ported/regression_forecast_family::numeric_from_cell",
        "ported/regression_forecast_family::numeric_scalar_from_eval",
        "ported/regression_forecast_family::bool_flag_from_eval_or_default",
        "ported/regression_forecast_family::collect_numeric_vector_from_eval",
        "ported/regression_forecast_family::collect_numeric_vector_arg",
        "ported/regression_forecast_family::NumericMatrix::cell",
        "ported/regression_forecast_family::NumericMatrix::transpose",
        "ported/regression_forecast_family::NumericMatrix::row_values",
        "ported/regression_forecast_family::collect_numeric_matrix_from_eval",
        "ported/regression_forecast_family::collect_numeric_matrix_arg",
        "ported/regression_forecast_family::sequence_predictors",
        "ported/regression_forecast_family::default_output_shape_for_known_y",
        "ported/regression_forecast_family::normalize_known_x_matrix",
        "ported/regression_forecast_family::prepare_predictor_input",
        "ported/regression_forecast_family::predictor_input_from_optional",
        "ported/regression_forecast_family::prediction_input_from_optional",
        "ported/regression_forecast_family::least_squares",
        "ported/regression_forecast_family::exact_product",
        "ported/regression_forecast_family::exactly_proportional",
        "ported/regression_forecast_family::linear_fit_from_data",
        "ported/regression_forecast_family::eval_value_from_output_shape"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L424-L426",
      "state": "close",
      "suite": null,
      "summary": "Close: 2 of 211 recorded answers differ in the last bits, worst 2 ULP"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.TREND.json",
  "name": "TREND",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n- **`FORECAST` / `FORECAST.LINEAR`** are the single-predictor, single-point special case. This\n  relationship is not decorative: the record attached to this page found that every natural\n  centred arrangement it raced reproduced `FORECAST`'s slope and never `TREND`'s, on the datasets\n  where the two disagree. Two Excel surfaces that ought to compute the same slope apparently do\n  not compute it the same way — and that is a finding about Excel's internals, arrived at by\n  elimination.\n- **`GROWTH`** is `TREND` on `ln y`: the exponential model `y = b·m^x`, fitted by least squares in\n  the log domain. Same module, same machinery, different link.\n- **`SLOPE`, `INTERCEPT`, `RSQ`, `STEYX`** are the scalar readouts of the same single-predictor\n  fit; [STEYX](FUNC.STEYX.md) tabulates the correspondence.\n- **Confused with**: `FORECAST.ETS` (exponential smoothing, an entirely different model),\n  charting trendlines (which fit the same model but display coefficients rounded for the label),\n  and `SLOPE`×`x` + `INTERCEPT` written out by hand, which is a *third* route to the same number\n  and need not agree with either of the first two in the last bits.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\nLeast squares is the best-studied problem in numerical linear algebra, and the whole literature\nconverges on one sentence: **do not form `XᵀX`.**\n\n**Why.** The normal equations square the condition number: `κ₂(XᵀX) = κ₂(X)²`. A design matrix\nwith a modest condition number of `10⁶` — easily produced by a quadratic fit on data that does not\nstraddle zero — yields a normal-equations system with condition number `10¹²`, and in double\nprecision that consumes most of the available accuracy before the solve begins. A Vandermonde\nmatrix from a cubic or higher polynomial fit is far worse; this is why the NIST StRD `Filip`\ndataset (a tenth-degree polynomial fit) is the standard executioner of regression\nimplementations.\n\n**The alternatives.** A Householder QR factorization `X = QR` reduces the problem to the\ntriangular system `Rβ̂ = Qᵀy` and works with `κ₂(X)`, not its square; a singular value\ndecomposition additionally handles rank deficiency gracefully and yields the minimum-norm\nsolution. These are the recommendations of Lawson & Hanson, Björck, Golub & Van Loan, and\nHigham's *Accuracy and Stability of Numerical Algorithms* chapter 20, and they are what LAPACK's\n`gels`/`gelsd` do. Solving normal equations with a Gauss–Jordan inverse — forming `(XᵀX)⁻¹`\nexplicitly and multiplying — is the worst option available on both accuracy and stability\ngrounds, and it is the one textbooks use to state the model.\n\n**Centring.** For a model with an intercept, subtracting the column means before the solve and\nrecovering `b = ȳ − Σ mⱼx̄ⱼ` afterwards is mathematically equivalent and numerically decisive: it\nremoves the offset that otherwise dominates every entry of `XᵀX`. With `const = FALSE` this route\nis closed, because there is no intercept to absorb the shift — which is exactly why the two\n`const` settings deserve separate treatment and separate testing.\n\n- A **centred candidate** kernel — the arrangement promoted for `FORECAST`, generalized to the\n  design matrix — does substantially better on the same witnesses. Its score is a *candidate*\n  score, not the shipping surface's; the record's reader warning says so, and this page repeats\n  it.\n- The record's `ruled_out` list is the interesting part, because each entry is a conclusion about\n  **Excel**, reached by elimination: any one-pass computational sum-of-squares formula is\n  refuted, because it explodes on the huge-offset dataset where Excel does not — so **Excel\n  centres**. Extended-precision-throughout arrangements are refuted as strictly worse. And every\n  natural centred variant raced — forward and reverse accumulation, extended precision, centred\n  QR by Householder, centred normal equations, fused-multiply-add dot products, symmetric versus\n  asymmetric centring, one- versus two-pass — reproduces `FORECAST`'s slope and never `TREND`'s.\n- The record's open question states the limit honestly: the exact operation graph producing\n  `TREND`'s slope on the residual datasets is **under-determined** by the available witnesses,\n  and the multivariate regime is entirely unprobed.\n\nThe figures behind all of that belong to the evidence layer rendered beside this page and are not\nrestated in this prose. The record also carries a warning this page must repeat in its own voice:\nthe catalogue's observation that the *prediction* step reproduces Excel given the coefficients is\na decomposition of the problem, not a pass rate, and **it must never be read as \"TREND matches\nExcel\"**.\n\nThe accuracy of Excel's regression outputs is also the subject of a published literature — Morten\nWelinder's work on Gnumeric's statistical functions, and the NIST StRD assessments by Knüsel and\nby McCullough & Wilson. The Handbook names those as the right reading and does not assert from\nthem what any current Excel build does.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number` values, generally as an array shaped by `new_x's`.\n\n- **Shape.** One fitted value per new observation. The orientation of the result follows the\n  orientation of `new_x's`, which is one of the two most common sources of `#REF!` and `#VALUE!`\n  from this function; the other is a design matrix whose predictor columns run the wrong way.\n- **Rank deficiency.** Collinear predictors — including the exactly-duplicated column that a\n  careless polynomial expansion produces — make `XᵀX` singular. What Excel does then is not\n  documented on this page.\n- **Fewer observations than parameters** is the same problem in a different dress and is equally\n  undocumented.\n- **Large offsets.** Data whose `x` values sit far from zero relative to their spread (times as\n  serial dates, sensor readings around a large baseline) is the regime where the uncentred and\n  centred arrangements of the same formula give visibly different answers. It is also the regime\n  the evidence record attached to this page found most diagnostic.\n- **Text, logicals and empty cells** in the data ranges follow the family's coercion policy. This\n  surface's module carries the open upstream defect stream `BUG-FUNC-028`, whose title names an\n  unswept conversion, text/date, array-lift and coercion gap; the Handbook cites it by name and\n  does not restate its contents.\n\n\n\n### Errors\n\n\nMicrosoft's `TREND` page carries no error table. That is itself a finding: a function with a\ndocumented rank-deficiency exposure, a documented orientation requirement, and a documented\noptional-argument default chain publishes **no** documented error conditions at all.\n\nWhat can be said honestly:\n\nNothing in this table is a documented Microsoft statement, and the Handbook has not verified any\nof it against Excel.\n\n\n",
    "sources": "- Microsoft, \"TREND function\" —\n  <https://support.microsoft.com/en-us/office/trend-function-e2f135f0-8827-4096-9873-9a7cf7b51ef1>\n  (syntax; the `y = mx + b` model and the statement that `TREND` fits a straight line using the\n  method of least squares; the `{1,2,3,…}` default for `known_x's`; the `new_x's` default; the\n  `const = FALSE` behaviour forcing `b = 0` with the `m` values adjusted; the requirement that\n  `known_y's` be a vector when there is more than one predictor; polynomial fitting by regressing\n  against powers of the same variable; and the array-entry rule). Retrieved for this page. The\n  page documents no error conditions.\n- Handbook evidence record `EV-MISC-0009` — the open discrepancy on `TREND`: the shipping\n  uncentred-normal-equations kernel with its Gauss–Jordan inverse and spurious `#NUM!` guard, the\n  centred candidate, the ruled-out arrangements (including the elimination establishing that\n  Excel centres), the `FORECAST`-slope coincidence, and the reader warning that the prediction\n  path's conditional result is not a statement that `TREND` matches Excel.\n- N. J. Higham, *Accuracy and Stability of Numerical Algorithms*, chapter 20 (least squares);\n  C. L. Lawson and R. J. Hanson, *Solving Least Squares Problems*; Å. Björck, *Numerical Methods\n  for Least Squares Problems*; G. H. Golub and C. F. Van Loan, *Matrix Computations* — the QR and\n  SVD alternatives to the normal equations, and the condition-squaring result.\n- The NIST Statistical Reference Datasets for linear regression (`Norris`, `Longley`, `Filip`,\n  the `Wampler` series) — the standard certified benchmarks.\n- M. Welinder's documentation of Gnumeric's statistical functions, and the Excel accuracy\n  assessments of R. Knüsel and of B. D. McCullough and B. Wilson — named as the standing\n  literature, not as evidence about any current build.\n- Handbook [The value universe](../model/01-value-universe.md) and\n  [Coercion and lifting](../model/02-coercion-and-lifting.md).\n- Handbook projections `data/functions/FUNC.TREND.json`, `data/presence/FUNC.TREND.json` (the\n  shared `regression_forecast_family` module) and `data/battery/FUNC.TREND.json`.\n\n",
    "version-differences": "The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.\n\n| Excel 16.0 build | Platform and CPU | Captured inputs |\n|---|---|---:|\n| 20131 | Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics | 12 |\n\nThe record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.\n\n[Recorded environments and comparison details](https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.TREND.json).",
    "what-it-does": "\n`TREND(known_y's, [known_x's], [new_x's], [const])` fits a linear model to the known data by the\n**method of least squares** — Microsoft's page says so in those words — and returns the fitted\nvalues of that model at the new `x` positions.\n\nWith one predictor the model is the familiar `y = m·x + b` that the documentation names. With\nseveral predictors it is\n\n    y = m₁x₁ + m₂x₂ + … + m_kx_k + b\n\nand `TREND` returns `ŷ* = X* β̂` where `β̂` minimizes `‖y − Xβ‖₂` over the known data. In matrix\nterms, with `X` the `n × (k+1)` design matrix whose first column is all ones (when `const` is\nTRUE or omitted):\n\n    β̂ = argmin ‖y − Xβ‖₂     ⟺     XᵀX β̂ = Xᵀy       (the normal equations)\n\nThe normal-equations characterization is *mathematically* correct and *numerically* the worst way\nto obtain `β̂`; that distinction is the entire subject of the Numerical notes section, and it is\nthe subject of the evidence record attached to this page.\n\nFor the single-predictor case the solution is explicit:\n\n    b_slope = Sxy / Sxx,     b_intercept = ȳ − b_slope·x̄\n\nwith `Sxx = Σ(x − x̄)²` and `Sxy = Σ(x − x̄)(y − ȳ)`. Two things follow that matter more than\nthey look:\n\n1. **The centred form is a different computation from the uncentred one.** `Sxx` written as\n   `Σ(x − x̄)²` and `Sxx` written as `Σx² − (Σx)²/n` are the same real number and wildly\n   different floating-point numbers when the data has a large mean relative to its spread.\n2. **`const = FALSE` removes the option to centre.** With the intercept forced to zero the model\n   is `y = m·x` and the estimator is `Σxy / Σx²` — an uncentred quantity by necessity. The two\n   settings of `const` are therefore not one algorithm with a flag; they are two.\n\n`TREND` is a *dynamic array* surface: it returns one fitted value per row of `new_x's`, so its\nresult is generally an array rather than a scalar.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Default when omitted |\n|---|---|---|\n| `known_y's` | \"The set of y-values you already know in the relationship y = mx + b\". Required. | — |\n| `known_x's` | \"An optional set of x-values you may already know\". | `{1, 2, 3, …}` the same size as `known_y's` |\n| `new_x's` | \"New x-values for which you want TREND to return corresponding y-values\". | the same as `known_x's` |\n| `const` | Logical: whether to force the constant `b` to zero. | TRUE — `b` is calculated normally |\n\nDocumented details worth stating precisely, because each one is a place readers get surprised:\n\n- **Omitting `known_x's` substitutes the index sequence** `{1,2,3,…}`. `TREND(A1:A12)` is a\n  regression against time-as-row-number, and it is a real model, not a degenerate one.\n- **Omitting `new_x's` re-uses `known_x's`**, which makes `TREND(y, x)` the vector of fitted\n  values — the in-sample predictions — rather than a forecast.\n- **`const = FALSE` sets `b = 0` and adjusts the `m` values so that `y = mx`.** It does not\n  simply drop the intercept from a fit computed with one; the whole fit changes.\n- **Several predictors are supported**, and when there is more than one, `known_y's` must be a\n  vector.\n- **Polynomial fitting** is documented as a use: regress against the same variable raised to\n  different powers, supplying `x`, `x²`, `x³` as separate predictor columns. This is worth\n  flagging as the numerically hardest thing `TREND` is documented to do — the Vandermonde design\n  matrix it produces is the standard example of an ill-conditioned least-squares problem.\n- **Array entry**: results that are arrays must be entered as array formulas with\n  Ctrl+Shift+Enter unless the build supports dynamic arrays, in which case Enter suffices.\n\n\n"
  },
  "signature": {
    "display": "TREND(known_ys, [known_xs], [new_xs], [const])",
    "parameters": [
      {
        "description": null,
        "name": "known_ys",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "known_xs",
        "optional": true,
        "repeats": false
      },
      {
        "description": null,
        "name": "new_xs",
        "optional": true,
        "repeats": false
      },
      {
        "description": null,
        "name": "const",
        "optional": true,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 4,
        "min": 1
      },
      "category": "Statistical functions",
      "classification": {
        "arg_preparation_profile": "RefsVisibleInAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "RefOnly",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Values predicted on the least-squares line fitted to known data",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns values along a linear trend",
        "microsoft_url": "https://support.microsoft.com/en-us/office/trend-function-e2f135f0-8827-4096-9873-9a7cf7b51ef1"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "TREND"
        },
        {
          "locale": "bg-BG",
          "name": "TREND"
        },
        {
          "locale": "cs-CZ",
          "name": "TREND"
        },
        {
          "locale": "da-DK",
          "name": "TENDENS"
        },
        {
          "locale": "de-DE",
          "name": "TREND"
        },
        {
          "locale": "el-GR",
          "name": "TREND"
        },
        {
          "locale": "en-AU",
          "name": "TREND"
        },
        {
          "locale": "en-GB",
          "name": "TREND"
        },
        {
          "locale": "en-US",
          "name": "TREND"
        },
        {
          "locale": "es-ES",
          "name": "TENDENCIA"
        },
        {
          "locale": "et-EE",
          "name": "TREND"
        },
        {
          "locale": "fi-FI",
          "name": "TRENDI"
        },
        {
          "locale": "fr-FR",
          "name": "TENDANCE*"
        },
        {
          "locale": "he-IL",
          "name": "TREND"
        },
        {
          "locale": "hr-HR",
          "name": "TREND"
        },
        {
          "locale": "hu-HU",
          "name": "TREND"
        },
        {
          "locale": "id-ID",
          "name": "TREND"
        },
        {
          "locale": "it-IT",
          "name": "TREND"
        },
        {
          "locale": "ja-JP",
          "name": "TREND"
        },
        {
          "locale": "ko-KR",
          "name": "TREND"
        },
        {
          "locale": "lt-LT",
          "name": "TREND"
        },
        {
          "locale": "lv-LV",
          "name": "TREND"
        },
        {
          "locale": "nb-NO",
          "name": "TREND"
        },
        {
          "locale": "nl-NL",
          "name": "TREND"
        },
        {
          "locale": "pl-PL",
          "name": "REGLINW"
        },
        {
          "locale": "pt-BR",
          "name": "TENDÊNCIA"
        },
        {
          "locale": "pt-PT",
          "name": "TENDÊNCIA"
        },
        {
          "locale": "ro-RO",
          "name": "TREND"
        },
        {
          "locale": "ru-RU",
          "name": "ТЕНДЕНЦИЯ"
        },
        {
          "locale": "sk-SK",
          "name": "TREND"
        },
        {
          "locale": "sl-SI",
          "name": "TREND"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "TREND"
        },
        {
          "locale": "sv-SE",
          "name": "TREND"
        },
        {
          "locale": "th-TH",
          "name": "TREND"
        },
        {
          "locale": "tr-TR",
          "name": "EĞİLİM"
        },
        {
          "locale": "uk-UA",
          "name": "TREND"
        },
        {
          "locale": "vi-VN",
          "name": "TREND"
        },
        {
          "locale": "zh-CN",
          "name": "TREND"
        },
        {
          "locale": "zh-HK",
          "name": "趨勢"
        },
        {
          "locale": "zh-TW",
          "name": "趨勢"
        }
      ],
      "signature": {
        "display": "TREND(known_ys, [known_xs], [new_xs], [const])",
        "parameters": [
          {
            "description": null,
            "name": "known_ys",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "known_xs",
            "optional": true,
            "repeats": false
          },
          {
            "description": null,
            "name": "new_xs",
            "optional": true,
            "repeats": false
          },
          {
            "description": null,
            "name": "const",
            "optional": true,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "TREND",
      "version_marker": null,
      "xlcall": {
        "code": "50",
        "symbol": "xlfTrend"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/trend-function-e2f135f0-8827-4096-9873-9a7cf7b51ef1"
  },
  "try_it": {
    "formula": "=TREND(1)"
  },
  "url": "https://handbook.dnacalc.com/functions/TREND.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "12 captured inputs are indexed for this environment. Capture dates: 2026-07-12 to 2026-07-12. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 20131",
      "platform": "Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.TREND.json"
      ]
    }
  ]
}