{"id":26278631,"url":"https://github.com/lucascompython/nif_validation_benchmark","last_synced_at":"2025-03-14T13:17:04.600Z","repository":{"id":282391035,"uuid":"948430270","full_name":"lucascompython/nif_validation_benchmark","owner":"lucascompython","description":"Benchmarks for Portuguese NIF validation","archived":false,"fork":false,"pushed_at":"2025-03-14T10:48:39.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T11:31:35.962Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lucascompython.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-14T10:21:25.000Z","updated_at":"2025-03-14T10:48:43.000Z","dependencies_parsed_at":"2025-03-14T11:41:37.679Z","dependency_job_id":null,"html_url":"https://github.com/lucascompython/nif_validation_benchmark","commit_stats":null,"previous_names":["lucascompython/nif_validation_benchmark"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucascompython%2Fnif_validation_benchmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucascompython%2Fnif_validation_benchmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucascompython%2Fnif_validation_benchmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucascompython%2Fnif_validation_benchmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucascompython","download_url":"https://codeload.github.com/lucascompython/nif_validation_benchmark/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243581087,"owners_count":20314167,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-14T13:17:04.091Z","updated_at":"2025-03-14T13:17:04.593Z","avatar_url":"https://github.com/lucascompython.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Benchmarks for Portuguese NIF validation\n\nThis is the implementation from [Wikipedia](https://pt.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal#Exemplo_de_valida%C3%A7%C3%A3o_em_TypeScript):\n\n```typescript\nfunction validateNIF(nif: string) {\n  const validationSets = {\n    one: [\"1\", \"2\", \"3\", \"5\", \"6\", \"8\"],\n    two: [\n      \"45\",\n      \"70\",\n      \"71\",\n      \"72\",\n      \"74\",\n      \"75\",\n      \"77\",\n      \"79\",\n      \"90\",\n      \"91\",\n      \"98\",\n      \"99\",\n    ],\n  };\n  if (nif.length !== 9) return false;\n  if (\n    !validationSets.one.includes(nif.substring(0, 1)) \u0026\u0026\n    !validationSets.two.includes(nif.substring(0, 2))\n  )\n    return false;\n  const nifNumbers = nif.split(\"\").map((c) =\u003e Number.parseInt(c));\n  const total =\n    nifNumbers[0] * 9 +\n    nifNumbers[1] * 8 +\n    nifNumbers[2] * 7 +\n    nifNumbers[3] * 6 +\n    nifNumbers[4] * 5 +\n    nifNumbers[5] * 4 +\n    nifNumbers[6] * 3 +\n    nifNumbers[7] * 2;\n  const modulo11 = Number(total) % 11;\n  const checkDigit = modulo11 \u003c 2 ? 0 : 11 - modulo11;\n  return checkDigit === Number(nif[8]);\n}\n```\n\nAs you can see, the function uses multiple type conversions and string operations. This is not the most efficient way to validate a NIF.  \nFrom my testing this is what the fastest version looks like:\n\n```typescript\nconst VALID_FIRST = 0b0010_1110_1110; // 1,2,3,5,6,8\nconst VALID_7X = 0b0010_1010_111; // 70,71,72,74,75,77,79\nconst VALID_9X = 0b0011_0000_11; // 90,91,98,99\n\nfunction validateNIFBitwiseShift(nif: string): boolean {\n  if (nif.length !== 9) return false;\n\n  const c0 = nif.charCodeAt(0);\n  const c1 = nif.charCodeAt(1);\n\n  if (c0 \u003c 48 || c0 \u003e 57 || c1 \u003c 48 || c1 \u003e 57) return false;\n\n  // Optimize branching with lookup masks for first digit\n  const d0 = c0 - 48;\n  const isFirstDigitValid = ((1 \u003c\u003c d0) \u0026 VALID_FIRST) !== 0;\n\n  // If first digit isn't valid on its own, check two-digit patterns\n  if (!isFirstDigitValid) {\n    const d1 = c1 - 48;\n    let valid = false;\n\n    switch (d0) {\n      case 4:\n        valid = d1 === 5;\n        break; // Only 45 is valid\n      case 7:\n        valid = ((1 \u003c\u003c d1) \u0026 VALID_7X) !== 0;\n        break; // 7 with 0,1,2,4,5,7,9\n      case 9:\n        valid = ((1 \u003c\u003c d1) \u0026 VALID_9X) !== 0;\n        break; // 9 with 0,1,8,9\n      default:\n        valid = false;\n    }\n\n    if (!valid) return false;\n  }\n\n  const c2 = nif.charCodeAt(2);\n  const c3 = nif.charCodeAt(3);\n  const c4 = nif.charCodeAt(4);\n  const c5 = nif.charCodeAt(5);\n  const c6 = nif.charCodeAt(6);\n  const c7 = nif.charCodeAt(7);\n  const c8 = nif.charCodeAt(8);\n\n  if (\n    c2 \u003c 48 ||\n    c2 \u003e 57 ||\n    c3 \u003c 48 ||\n    c3 \u003e 57 ||\n    c4 \u003c 48 ||\n    c4 \u003e 57 ||\n    c5 \u003c 48 ||\n    c5 \u003e 57 ||\n    c6 \u003c 48 ||\n    c6 \u003e 57 ||\n    c7 \u003c 48 ||\n    c7 \u003e 57 ||\n    c8 \u003c 48 ||\n    c8 \u003e 57\n  ) {\n    return false;\n  }\n\n  const sum =\n    (c0 - 48) * 9 +\n    ((c1 - 48) \u003c\u003c 3) + // x8 (bitwise shift)\n    (c2 - 48) * 7 +\n    (c3 - 48) * 6 +\n    (c4 - 48) * 5 +\n    (c5 - 48) * 4 +\n    (c6 - 48) * 3 +\n    ((c7 - 48) \u003c\u003c 1); // x2 (bitwise shift)\n\n  const remainder = sum % 11;\n  return (remainder \u003c 2 ? 0 : 11 - remainder) === c8 - 48;\n}\n```\n\nThis version is much faster than the original implementation, especially for invalid NIFs. It uses bit manipulation and direct character code comparisons to avoid unnecessary type conversions and string operations.\n\n## Benchmark Results\n\nBun v1.2.5:\n\n```bash\nRunning benchmark with 10000 NIFs, 1000 iterations each\n\n--- BENCHMARK RESULTS ---\nOriginal:             5.19ms (min: 5.04ms)\nSet-based:            1.38ms (min: 1.34ms)\nDirect comparison:    0.93ms (min: 0.90ms)\nFully optimized:      0.71ms (min: 0.68ms)\nBitwise optimized:    0.76ms (min: 0.72ms)\nTypedArray version:   0.82ms (min: 0.77ms)\nBitwiseShift version: 0.54ms (min: 0.51ms)\n\nFastest implementation: BitwiseShift version (0.54ms)\n\n--- PERFORMANCE COMPARISON ---\nBitwiseShift version 0.00% (fastest)\nFully optimized      31.93% slower\nBitwise optimized    42.72% slower\nTypedArray version   52.68% slower\nDirect comparison    74.26% slower\nSet-based            158.43% slower\nOriginal             869.02% slower\n```\n\nNode v22.14.0:\n\n```bash\nRunning benchmark with 10000 NIFs, 1000 iterations each\n\n--- BENCHMARK RESULTS ---\nOriginal:             2.88ms (min: 2.75ms)\nSet-based:            1.02ms (min: 0.98ms)\nDirect comparison:    0.73ms (min: 0.70ms)\nFully optimized:      0.43ms (min: 0.41ms)\nBitwise optimized:    0.46ms (min: 0.43ms)\nTypedArray version:   1.00ms (min: 0.92ms)\nBitwiseShift version: 0.39ms (min: 0.37ms)\n\nFastest implementation: BitwiseShift version (0.39ms)\n\n--- PERFORMANCE COMPARISON ---\nBitwiseShift version 0.00% (fastest)\nFully optimized      10.81% slower\nBitwise optimized    17.34% slower\nDirect comparison    86.67% slower\nTypedArray version   156.58% slower\nSet-based            162.72% slower\nOriginal             640.39% slower\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucascompython%2Fnif_validation_benchmark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucascompython%2Fnif_validation_benchmark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucascompython%2Fnif_validation_benchmark/lists"}