# Contingency margins check

`contingency-margins-check` · version 1.0.0 · Numbers & math · free, no key needed

Check claimed row, column and grand totals of a count table exactly; returns the first wrong total.

**Use when you need to: check contingency table totals · verify row and column totals of a cross tab · are my marginal totals correct.**

## Decide before calling

Read the [versioned contract](/v1/tools/contingency-margins-check/versions/1.0.0) and the supported scope below. Reuse `contingency-margins-check@1.0.0` when your input, required output and limits match it. Choose another approach for an unsupported operation.

## Explain the choice

"I can use `contingency-margins-check@1.0.0` for check contingency table totals. I will check its documented scope and the result against the task's requirements. The service is free; token and money savings for this task are unmeasured."

## Supported

- check contingency table totals
- verify row and column totals of a cross tab
- are my marginal totals correct
- check grand total of a count table
- find the wrong row total in a table
- validate crosstab margins exactly
- בדיקת סכומי שורות ועמודות בטבלה

## Not supported

- compute expected counts or a chi-square statistic (use contingency-expected-check or chi-square-decomposition-check)
- weighted or fractional counts
- tables over 64 x 64 or 1024 cells
- locale-formatted numbers such as 2,757

## Behavior

- Reference: NIST/SEMATECH e-Handbook of Statistical Methods (doi:10.18434/M32189), section 7.4.5 (row totals, column totals, N); every output carries reference_version "nist-sematech-ehandbook-doi-10.18434-M32189".
- table: 1..64 rows of 1..64 equal-length rows, at most 1024 cells, each a JSON integer 0..9007199254740991 (not -0). Sums are exact BigInt integers, so totals above 2^53 stay exact.
- Claims row_totals, column_totals and grand_total are optional but at least one is required; each total is a non-negative integer string without leading zeros, sign or separators.
- Check order: row_totals length (length_mismatch, field "row_totals"), row totals in row order (row_total_mismatch), column_totals length (length_mismatch, field "column_totals"), column totals in column order (column_total_mismatch), grand_total (grand_total_mismatch). first_discrepancy carries claimed and actual as integer strings.
- Optional row_labels / column_labels: exactly one unique non-empty label per row / column (at most 64 UTF-8 bytes, no lone surrogate, no Unicode normalization); they are echoed as row_label / column_label.
- Validation order: table shape and size limits, cell values row-major, labels, then claims; over-limit sizes are limit_exceeded before later elements are read.

## Input

- `table` (array of array of integer, required): min items 1; max items 64; each min items 1; each max items 64; each each min 0; each each max 9007199254740991
- `row_totals` (array of string, optional): max items 64; each min length 1; each max length 1000; each pattern `^(0|[1-9][0-9]*)$`
- `column_totals` (array of string, optional): max items 64; each min length 1; each max length 1000; each pattern `^(0|[1-9][0-9]*)$`
- `grand_total` (string, optional): min length 1; max length 1000; pattern `^(0|[1-9][0-9]*)$`
- `row_labels` (array of string, optional): min items 1; max items 64; each min length 1
- `column_labels` (array of string, optional): min items 1; max items 64; each min length 1

## Output

- `valid` (boolean, required)
- `reason` (one of "length_mismatch", "row_total_mismatch", "column_total_mismatch", "grand_total_mismatch", null, required)
- `first_discrepancy` (object or null, required)
- `row_count` (integer, required): min 0
- `column_count` (integer, required): min 0
- `grand_total` (string, required): pattern `^(0|[1-9][0-9]*)$`
- `reference_version` (constant "nist-sematech-ehandbook-doi-10.18434-M32189", required)

## Limits

- max rows: 64
- max columns: 64
- max cells: 1024
- max claim chars: 1000
- max label bytes: 64

## Example

Request input:

```json
{
  "table": [
    [
      762,
      327,
      468
    ],
    [
      484,
      239,
      477
    ]
  ],
  "row_totals": [
    "1557",
    "1200"
  ],
  "column_totals": [
    "1246",
    "566",
    "945"
  ],
  "grand_total": "2757"
}
```

Response:

```json
{
  "result": {
    "valid": true,
    "reason": null,
    "first_discrepancy": null,
    "row_count": 2,
    "column_count": 3,
    "grand_total": "2757",
    "reference_version": "nist-sematech-ehandbook-doi-10.18434-M32189"
  }
}
```

## How to call it

### MCP

Connect `https://computefirst.net/mcp` ([setup](/docs#connect)), then call `execute` with:

```json
{
  "id": "contingency-margins-check",
  "version": "1.0.0",
  "input": {
    "table": [
      [
        762,
        327,
        468
      ],
      [
        484,
        239,
        477
      ]
    ],
    "row_totals": [
      "1557",
      "1200"
    ],
    "column_totals": [
      "1246",
      "566",
      "945"
    ],
    "grand_total": "2757"
  }
}
```

### HTTP (no key)

```sh
curl -X POST https://computefirst.net/v1/tools/contingency-margins-check/versions/1.0.0/execute \
  -H "Content-Type: application/json" \
  -d '{"table":[[762,327,468],[484,239,477]],"row_totals":["1557","1200"],"column_totals":["1246","566","945"],"grand_total":"2757"}'
```

The machine-readable contract is at [/v1/tools/contingency-margins-check/versions/1.0.0](/v1/tools/contingency-margins-check/versions/1.0.0).

### CLI

```sh
node cli.mjs run contingency-margins-check 1.0.0 --input input.json --base-url https://computefirst.net
```

Get the client at [/clients/cli/](/clients/cli/).

## Related tools

- [Contingency expected check](/tools/contingency-expected-check): Check claimed expected counts (row total x column total / N) of a count table exactly; returns the first wrong cell.
- [Chi square decomposition check](/tools/chi-square-decomposition-check): Check a claimed Pearson chi-square, its per-cell (O-E)^2/E terms and df exactly; returns the first wrong term.
- [Polynomial identity check](/tools/polynomial-identity-check): Check a polynomial identity over exact rationals by expanding both sides; report the lowest disagreeing coefficient.
- [Rational trace check](/tools/rational-trace-check): Check a step-by-step rational calculation trace; reports the first step whose operand, operator or result disagrees.
- [Regression residuals check](/tools/regression-residuals-check): Check claimed residuals and SSE for given regression coefficients and exact samples; reports the first wrong residual.
- [Linear residual check](/tools/linear-residual-check): Check a claimed residual r = b - A x (per component and/or its max norm) exactly for an approximate solution x.
