{
  "schemaVersion": 1,
  "slug": "gcf-calculator",
  "category": "math",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "d02db586773f75d130ee6261cbc570f84b2ddce5ebf4899158963a2b76eaefe2",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/gcf-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "g = gcd(|n₁|,…,|nₖ|); l = lcm(|n₁|,…,|nₖ|); ratio = |n₁|/g : … : |nₖ|/g; d(g) = Πᵢ(eᵢ + 1)",
    "vars": [
      [
        "A",
        "First number (≥ 0)"
      ],
      [
        "B",
        "Second number (≥ 0)"
      ],
      [
        "C",
        "third positive integer (0 = omit)"
      ],
      [
        "g",
        "greatest common factor"
      ],
      [
        "l",
        "least common multiple"
      ],
      [
        "e_i",
        "exponent of prime factor i of g"
      ],
      [
        "d(g)",
        "common-factor count"
      ]
    ],
    "note": "Find the GCF, exact LCM and simplified ratio of two or three numbers, or a list of 2–20 integers. List mode uses absolute values. The optional third 0 is omitted only in two/three-number mode; zeros in a list are included. See Euclidean steps and all positive common factors."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-28",
    "sources": [
      {
        "name": "Wolfram MathWorld — Greatest Common Divisor",
        "url": "https://mathworld.wolfram.com/GreatestCommonDivisor.html"
      }
    ],
    "implementationHash": "d02db586773f75d130ee6261cbc570f84b2ddce5ebf4899158963a2b76eaefe2",
    "basis": "The Euclidean algorithm repeatedly divides and takes the remainder until it reaches zero; the last nonzero value is the GCF. For a list, repeat with each next number. Divide every input by the GCF to simplify the ratio. The positive common factors are the positive divisors of the GCF. LCM arithmetic uses exact integers, including results larger than the safe floating-point range. In pair mode a third value of 0 is omitted. In list mode zeros are included, so a list containing zero has LCM 0 unless the whole input is zero, which this tool rejects. Negative values are accepted only in list mode and are converted to absolute values. P1 consolidation retains the core model and adds input modes or derived outputs. The migration report records the input/output union and known-answer checks.",
    "limitations": "Find the GCF, exact LCM and simplified ratio of two or three numbers, or a list of 2–20 integers. List mode uses absolute values. The optional third 0 is omitted only in two/three-number mode; zeros in a list are included. See Euclidean steps and all positive common factors. Added display totals and migration adapters are implementation behavior, not independently validated claims."
  },
  "contract": {
    "compute": "const mergedResult=(()=>{if((true&&![\"gcf\", \"lcm\"].includes(String(resultKind)))||(true&&![\"pair\", \"list\"].includes(String(mode))))return{__error:'inputError'};\nif(([\"pair\"].includes(String(mode))&&(!Number.isFinite(numberA)||numberA<0||numberA>1000000000))||([\"pair\"].includes(String(mode))&&(!Number.isFinite(numberB)||numberB<0||numberB>1000000000))||([\"pair\"].includes(String(mode))&&(!Number.isFinite(numberC)||numberC<0||numberC>1000000000)))return{__error:'inputError'};\nconst invalid={gcf:null,lcm:null,simplifiedRatio:null,commonFactorCount:null,__error:'inputError'};let nums;\nif(mode==='list'){const tokens=String(numbers).trim().split(/[\\s,;]+/);if(tokens.length<2||tokens.length>20||tokens.some(s=>!/^[-+]?\\d+$/.test(s)))return invalid;nums=tokens.map(Number);if(nums.some(n=>!Number.isSafeInteger(n)||Math.abs(n)>1e9))return invalid;nums=nums.map(Math.abs);}else if(mode==='pair'){if(![numberA,numberB,numberC].every(n=>Number.isSafeInteger(n)&&n>=0&&n<=1e9))return invalid;nums=numberC>0?[numberA,numberB,numberC]:[numberA,numberB];}else return invalid;\nif(nums.every(n=>n===0))return {...invalid,__error:'allZero'};\nconst steps=[];const gcd2=(x,y,trace)=>{while(y){const remainder=x%y;if(trace)steps.push({a:x,b:y,q:Math.floor(x/y),r:remainder,equation:x+' = '+Math.floor(x/y)+' × '+y+' + '+remainder});x=y;y=remainder;}return x;};\nlet g=nums[0],l=BigInt(nums[0]);for(let i=1;i<nums.length;i++){g=gcd2(g,nums[i],true);const y=BigInt(nums[i]);if(l===0n||y===0n)l=0n;else{let a=l,b=y;while(b){const r=a%b;a=b;b=r;}l=l/a*y;}}\nconst small=[],large=[];for(let d=1;d*d<=g;d++)if(g%d===0){small.push(d);if(d*d!==g)large.push(g/d);}const divisors=small.concat(large.reverse());\nreturn {both:String(BigInt(g)*l),gcf:g,lcm:String(l),simplifiedRatio:nums.map(v=>v/g).join(' : '),commonFactorCount:divisors.length,__divisors:divisors,__euclidSteps:steps,__numbers:nums};\n})();return mergedResult.__error?{\"gcf\":null,\"lcm\":null,\"simplifiedRatio\":null,\"commonFactorCount\":null,\"both\":null,...mergedResult}:mergedResult;",
    "inputs": [
      {
        "name": "resultKind",
        "type": "select",
        "default": "gcf",
        "options": [
          {
            "value": "gcf"
          },
          {
            "value": "lcm"
          }
        ]
      },
      {
        "name": "mode",
        "type": "select",
        "default": "pair",
        "options": [
          {
            "value": "pair"
          },
          {
            "value": "list"
          }
        ]
      },
      {
        "name": "numberA",
        "type": "number",
        "default": 24,
        "min": 0,
        "max": 1000000000,
        "step": 1,
        "requiredValue": true,
        "strictRange": true,
        "showWhen": {
          "mode": [
            "pair"
          ]
        }
      },
      {
        "name": "numberB",
        "type": "number",
        "default": 36,
        "min": 0,
        "max": 1000000000,
        "step": 1,
        "requiredValue": true,
        "strictRange": true,
        "showWhen": {
          "mode": [
            "pair"
          ]
        }
      },
      {
        "name": "numberC",
        "type": "number",
        "default": 0,
        "min": 0,
        "max": 1000000000,
        "step": 1,
        "requiredValue": true,
        "strictRange": true,
        "showWhen": {
          "mode": [
            "pair"
          ]
        }
      },
      {
        "name": "numbers",
        "type": "text",
        "default": "24, 36, 60",
        "multiline": true,
        "showWhen": {
          "mode": [
            "list"
          ]
        },
        "preserveEmpty": true
      }
    ],
    "outputs": [
      {
        "name": "gcf",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "lcm",
        "precision": 0,
        "unit": "",
        "type": "decimal"
      },
      {
        "name": "simplifiedRatio",
        "precision": 0,
        "unit": "",
        "type": "text",
        "display": "tokens",
        "separator": " : "
      },
      {
        "name": "commonFactorCount",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "both",
        "precision": 0,
        "unit": "",
        "type": "decimal"
      }
    ],
    "interpret": null
  }
}
