> ## Documentation Index
> Fetch the complete documentation index at: https://numpyts.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# numpy-ts vs. NumPy (Native)

export const BenchmarkReport = ({data, detailUrl}) => {
  const summary = data?.summary || ({});
  const meta = data?.meta || ({});
  const categories = Array.isArray(data?.categories) ? data.categories : [];
  const dtypeStats = Array.isArray(data?.dtypeStats) ? data.dtypeStats : [];
  const THEME_COLORS = {
    light: {
      cardBg: '#ffffff',
      mutedCardBg: '#fafafa',
      border: '#e5e7eb',
      text: '#111827',
      mutedText: '#6b7280',
      chartTrack: '#f3f4f6',
      tableHeadBg: '#f9fafb',
      tableHeadText: '#374151',
      tableRowBorder: '#e5e7eb',
      tableRowAlt: '#fafafa',
      ratioGoodText: '#1f9d55',
      ratioGoodBg: '#dcfce7',
      ratioOkText: '#b7791f',
      ratioOkBg: '#fef3c7',
      ratioBadText: '#c53030',
      ratioBadBg: '#fee2e2',
      chartGood: '#22c55e',
      chartOk: '#f59e0b',
      chartBad: '#ef4444'
    },
    dark: {
      cardBg: '#1e1e1e',
      mutedCardBg: '#1a1a1a',
      border: '#333333',
      text: '#d4d4d4',
      mutedText: '#888888',
      chartTrack: '#2a2a2a',
      tableHeadBg: '#161616',
      tableHeadText: '#d4d4d4',
      tableRowBorder: '#333333',
      tableRowAlt: '#161616',
      ratioGoodText: '#86efac',
      ratioGoodBg: '#14532d',
      ratioOkText: '#fde68a',
      ratioOkBg: '#78350f',
      ratioBadText: '#fca5a5',
      ratioBadBg: '#7f1d1d',
      chartGood: '#22c55e',
      chartOk: '#f59e0b',
      chartBad: '#ef4444'
    }
  };
  const DTYPE_COLORS = {
    float64: {
      bg: '#3b6cc9',
      text: '#ffffff'
    },
    float32: {
      bg: '#4a80d8',
      text: '#ffffff'
    },
    float16: {
      bg: '#6196e2',
      text: '#ffffff'
    },
    complex128: {
      bg: '#8b5cc6',
      text: '#ffffff'
    },
    complex64: {
      bg: '#a478d4',
      text: '#ffffff'
    },
    int64: {
      bg: '#2a8a82',
      text: '#ffffff'
    },
    int32: {
      bg: '#3ba69d',
      text: '#ffffff'
    },
    int16: {
      bg: '#55bfb7',
      text: '#1a4a46'
    },
    int8: {
      bg: '#7ad4cd',
      text: '#1a4a46'
    },
    uint64: {
      bg: '#c98a2e',
      text: '#ffffff'
    },
    uint32: {
      bg: '#d9a044',
      text: '#3a2400'
    },
    uint16: {
      bg: '#e4b85e',
      text: '#3a2400'
    },
    uint8: {
      bg: '#eecb7c',
      text: '#3a2400'
    },
    bool: {
      bg: '#cc4466',
      text: '#ffffff'
    }
  };
  const DTYPE_RE = /\s+(float64|float32|float16|complex128|complex64|int64|int32|int16|int8|uint64|uint32|uint16|uint8|bool)$/;
  const [isDarkMode, setIsDarkMode] = useState(() => document.documentElement.classList.contains('dark'));
  const [openCategories, setOpenCategories] = useState({});
  const [isMetaOpen, setIsMetaOpen] = useState(false);
  const [isDtypeOpen, setIsDtypeOpen] = useState(false);
  const [isMobile, setIsMobile] = useState(() => window.innerWidth < 640);
  const [isNarrow, setIsNarrow] = useState(() => window.innerWidth < 900);
  const [detailMap, setDetailMap] = useState(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const detailFetched = useRef(false);
  const fetchDetail = () => {
    if (detailFetched.current || !detailUrl) return;
    detailFetched.current = true;
    setDetailLoading(true);
    const absUrl = new URL(detailUrl, window.location.href).href;
    const buildMap = d => {
      const cats = d && d.categories || [];
      const m = {};
      for (const c of cats) m[c.name] = c.benchmarks || [];
      return m;
    };
    const fallback = () => {
      fetch(absUrl).then(r => r.json()).then(d => setDetailMap(buildMap(d))).catch(() => {
        detailFetched.current = false;
      }).finally(() => setDetailLoading(false));
    };
    try {
      if (typeof Worker === 'undefined' || typeof Blob === 'undefined') return fallback();
      const code = "self.onmessage=async e=>{try{const{url,key}=e.data;const r=await fetch(url);const d=await r.json();const cats=(d&&d[key])||[];const m={};for(const c of cats)m[c.name]=c.benchmarks||[];self.postMessage({ok:true,map:m});}catch(err){self.postMessage({ok:false});}}";
      const blobUrl = URL.createObjectURL(new Blob([code], {
        type: 'application/javascript'
      }));
      const worker = new Worker(blobUrl);
      const cleanup = () => {
        worker.terminate();
        URL.revokeObjectURL(blobUrl);
      };
      worker.onmessage = e => {
        if (e.data && e.data.ok) setDetailMap(e.data.map); else detailFetched.current = false;
        setDetailLoading(false);
        cleanup();
      };
      worker.onerror = () => {
        detailFetched.current = false;
        setDetailLoading(false);
        cleanup();
      };
      worker.postMessage({
        url: absUrl,
        key: 'categories'
      });
    } catch {
      fallback();
    }
  };
  useEffect(() => {
    if (!detailUrl) return;
    let ricId, timeoutId;
    const schedule = () => {
      const ric = window.requestIdleCallback;
      if (ric) ricId = ric(() => fetchDetail(), {
        timeout: 2000
      }); else timeoutId = setTimeout(fetchDetail, 200);
    };
    if (document.readyState === 'complete') schedule(); else window.addEventListener('load', schedule, {
      once: true
    });
    return () => {
      window.removeEventListener('load', schedule);
      if (ricId && window.cancelIdleCallback) window.cancelIdleCallback(ricId);
      if (timeoutId) clearTimeout(timeoutId);
    };
  }, []);
  const toggleCategory = name => {
    fetchDetail();
    setOpenCategories(prev => ({
      ...prev,
      [name]: !prev[name]
    }));
  };
  useEffect(() => {
    const observer = new MutationObserver(() => {
      setIsDarkMode(document.documentElement.classList.contains('dark'));
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => observer.disconnect();
  }, []);
  useEffect(() => {
    const handler = () => {
      setIsMobile(window.innerWidth < 640);
      setIsNarrow(window.innerWidth < 900);
    };
    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);
  const colors = THEME_COLORS[isDarkMode ? 'dark' : 'light'];
  const HoverBar = useMemo(() => function HoverBar({tip, width, color, rounded, opacity, isDarkMode}) {
    const [show, setShow] = useState(false);
    const [pos, setPos] = useState(null);
    const ref = useRef(null);
    const lastPointerType = useRef('mouse');
    useEffect(() => {
      if (!show) {
        setPos(null);
        return;
      }
      const updatePos = () => {
        if (!ref.current) return;
        const r = ref.current.getBoundingClientRect();
        setPos({
          top: r.top,
          left: r.left + r.width / 2
        });
      };
      updatePos();
      const onDocPointerDown = e => {
        if (ref.current && !ref.current.contains(e.target)) setShow(false);
      };
      document.addEventListener('pointerdown', onDocPointerDown);
      window.addEventListener('scroll', updatePos, true);
      window.addEventListener('resize', updatePos);
      return () => {
        document.removeEventListener('pointerdown', onDocPointerDown);
        window.removeEventListener('scroll', updatePos, true);
        window.removeEventListener('resize', updatePos);
      };
    }, [show]);
    return <div ref={ref} style={{
      height: '100%',
      width,
      position: 'relative',
      cursor: 'default'
    }} onPointerEnter={e => {
      if (e.pointerType === 'mouse') setShow(true);
    }} onPointerLeave={e => {
      if (e.pointerType === 'mouse') setShow(false);
    }} onPointerDown={e => {
      lastPointerType.current = e.pointerType;
    }} onClick={() => {
      if (lastPointerType.current !== 'mouse') setShow(s => !s);
    }}>
        <div style={{
      height: '100%',
      width: '100%',
      background: color,
      borderRadius: rounded ? 7 : 0,
      opacity: opacity ?? 1,
      filter: show ? 'brightness(1.3)' : 'none',
      transition: 'filter 0.15s'
    }} />
        {tip && show && pos && <div style={{
      position: 'fixed',
      top: pos.top - 6,
      left: pos.left,
      transform: 'translate(-50%, -100%)',
      padding: '4px 8px',
      borderRadius: 6,
      background: isDarkMode ? '#2a2a2a' : '#111',
      color: '#fff',
      fontSize: 11,
      whiteSpace: 'nowrap',
      zIndex: 2147483647,
      pointerEvents: 'none',
      boxShadow: '0 2px 8px rgba(0,0,0,0.4)'
    }}>
            {tip}
          </div>}
      </div>;
  }, []);
  const BenchmarkName = ({name}) => {
    const s = String(name);
    const m = s.match(DTYPE_RE);
    const dtype = m ? m[1] : 'float64';
    const base = m ? s.slice(0, -m[0].length) : s;
    const dc = DTYPE_COLORS[dtype] || DTYPE_COLORS.float64;
    return <>
        {base}{' '}
        <span style={{
      display: 'inline-block',
      fontSize: '0.72em',
      fontWeight: 600,
      padding: '2px 8px',
      borderRadius: 999,
      background: dc.bg,
      color: dc.text,
      verticalAlign: 'middle',
      whiteSpace: 'nowrap'
    }}>
          {dtype}
        </span>
      </>;
  };
  const formatOps = ops => {
    if (!Number.isFinite(ops) || ops <= 0) return '-';
    if (ops >= 1_000_000_000) return `${(ops / 1_000_000_000).toFixed(2)}B/s`;
    if (ops >= 1_000_000) return `${(ops / 1_000_000).toFixed(2)}M/s`;
    if (ops >= 1_000) return `${(ops / 1_000).toFixed(2)}K/s`;
    return `${ops.toFixed(1)}/s`;
  };
  const formatRatio = ratio => {
    if (!Number.isFinite(ratio)) return '-';
    return `${ratio.toFixed(2)}x`;
  };
  const ratioTip = ratio => {
    if (!Number.isFinite(ratio)) return '';
    return ratio >= 1 ? `${ratio.toFixed(2)}x faster than NumPy` : `${ratio.toFixed(2)}x slower than NumPy`;
  };
  const RatioDisplay = ({ratio, size}) => {
    if (!Number.isFinite(ratio)) return <span>-</span>;
    const numSize = size === 'lg' ? 28 : 20;
    const suffixSize = size === 'lg' ? 13 : 11;
    return <span>
        <span style={{
      fontSize: numSize,
      fontWeight: 700,
      color: colors.text
    }}>{ratio.toFixed(2)}x</span>
        <span style={{
      fontSize: suffixSize,
      fontWeight: 400,
      color: colors.mutedText,
      marginLeft: 4
    }}>{ratio >= 1 ? 'faster than NumPy' : 'slower than NumPy'}</span>
      </span>;
  };
  const ratioColor = ratio => {
    if (ratio >= 1) return colors.ratioGoodText;
    if (ratio >= 0.75) return colors.ratioOkText;
    return colors.ratioBadText;
  };
  const ratioBg = ratio => {
    if (ratio >= 1) return colors.ratioGoodBg;
    if (ratio >= 0.75) return colors.ratioOkBg;
    return colors.ratioBadBg;
  };
  const chartColor = ratio => {
    if (ratio >= 1) return colors.chartGood;
    if (ratio >= 0.75) return colors.chartOk;
    return colors.chartBad;
  };
  const SummaryCard = ({label, value, style}) => <div style={{
    border: `1px solid ${colors.border}`,
    borderRadius: 10,
    padding: 14,
    background: colors.cardBg,
    ...style
  }}>
      <div style={{
    fontSize: 12,
    color: colors.mutedText,
    marginBottom: 6
  }}>{label}</div>
      <div style={{
    fontSize: 28,
    fontWeight: 700,
    color: colors.text
  }}>{value}</div>
    </div>;
  const BASELINE_PCT = 20;
  const barScale = (value, max) => {
    if (value <= 0) return 2;
    if (value <= 1) return Math.max(2, BASELINE_PCT * value);
    if (max <= 1) return BASELINE_PCT;
    return Math.min(100, BASELINE_PCT + Math.log(value) / Math.log(max) * (100 - BASELINE_PCT));
  };
  const BarTrack = ({children}) => <div style={{
    background: colors.chartTrack,
    height: 14,
    borderRadius: 7,
    position: 'relative'
  }}>
      <div style={{
    position: 'absolute',
    left: `${BASELINE_PCT}%`,
    top: 0,
    bottom: 0,
    width: 1,
    borderLeft: `1px dashed ${colors.mutedText}`,
    opacity: 0.4,
    zIndex: 1
  }} />
      {children}
    </div>;
  const maxCategorySpeedup = Math.max(...categories.map(c => c.avgSpeedup || 0), 1);
  const maxDtypeSpeedup = Math.max(...dtypeStats.map(d => d.avgSpeedup || 0), 1);
  const barGridCols = isMobile ? '90px 1fr 44px' : '140px 1fr 52px';
  return <div style={{
    color: colors.text
  }}>
      <div style={{
    display: 'grid',
    gap: 12,
    gridTemplateColumns: isMobile ? '1fr 1fr' : isNarrow ? '1fr' : '2fr 1fr 1fr',
    marginBottom: 20
  }}>
        <SummaryCard label="Average" value={<RatioDisplay ratio={summary.avgSpeedup} size="lg" />} style={isMobile ? {
    gridColumn: '1 / -1'
  } : undefined} />
        <SummaryCard label="Best case" value={formatRatio(summary.bestCase)} />
        <SummaryCard label="Worst case" value={formatRatio(summary.worstCase)} />
      </div>

      <div style={{
    border: `1px solid ${colors.border}`,
    borderRadius: 10,
    padding: 16,
    background: colors.cardBg,
    marginBottom: 20
  }}>
        <div style={{
    fontSize: 16,
    fontWeight: 600,
    marginBottom: 12,
    color: colors.text
  }}>Average Performance vs. NumPy by Category</div>
        <div style={{
    display: 'grid',
    gap: 10
  }}>
          {categories.map((category, catIdx) => {
    const ratio = Number(category.avgSpeedup) || 0;
    const widthPct = barScale(ratio, maxCategorySpeedup);
    return <div key={String(category.name)} style={{
      display: 'grid',
      gridTemplateColumns: barGridCols,
      gap: 10,
      alignItems: 'center'
    }}>
                <div style={{
      fontFamily: 'monospace',
      fontSize: 12,
      color: colors.text,
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      whiteSpace: 'nowrap'
    }}>
                  <a href={`#cat-${String(category.name).replace(/\s+/g, '-').toLowerCase()}`} onClick={e => {
      e.preventDefault();
      fetchDetail();
      const catName = String(category.name);
      setOpenCategories(prev => ({
        ...prev,
        [catName]: true
      }));
      setTimeout(() => {
        const el = document.getElementById(`cat-${catName.replace(/\s+/g, '-').toLowerCase()}`);
        if (el) el.scrollIntoView({
          behavior: 'smooth',
          block: 'start'
        });
      }, 50);
    }} style={{
      color: 'inherit',
      textDecoration: 'none',
      cursor: 'pointer'
    }} onMouseEnter={e => e.currentTarget.style.textDecoration = 'underline'} onMouseLeave={e => e.currentTarget.style.textDecoration = 'none'}>{String(category.name)}</a>
                </div>
                <BarTrack>
                  <HoverBar tip={ratioTip(ratio)} width={`${widthPct}%`} color={chartColor(ratio)} rounded isDarkMode={isDarkMode} />
                </BarTrack>
                <div style={{
      textAlign: 'right',
      fontWeight: 600,
      fontSize: 12,
      color: colors.text
    }}>{formatRatio(ratio)}</div>
              </div>;
  })}
        </div>
      </div>

      {dtypeStats.length > 0 && <div style={{
    border: `1px solid ${colors.border}`,
    borderRadius: 10,
    background: colors.cardBg,
    marginBottom: 20,
    overflow: 'hidden'
  }}>
          <button onClick={() => setIsDtypeOpen(v => !v)} style={{
    display: 'flex',
    alignItems: 'center',
    gap: 6,
    width: '100%',
    padding: 14,
    background: 'transparent',
    border: 'none',
    cursor: 'pointer',
    fontWeight: 600,
    fontSize: 14,
    color: colors.text,
    textAlign: 'left'
  }}>
            <span style={{
    fontSize: 10,
    display: 'inline-block',
    transform: isDtypeOpen ? 'rotate(90deg)' : 'rotate(0deg)',
    transition: 'transform 0.15s'
  }}>▶</span>
            Average Performance by DType
          </button>
          <div style={{
    maxHeight: isDtypeOpen ? 2000 : 0,
    overflow: isDtypeOpen ? 'visible' : 'hidden',
    transition: isDtypeOpen ? 'max-height 0.4s ease-in' : 'max-height 0.3s ease-out'
  }}>
            <div style={{
    padding: '0 14px 14px',
    display: 'grid',
    gap: 10
  }}>
              {dtypeStats.map(({dtype, count, avgSpeedup}) => {
    const widthPct = barScale(avgSpeedup, maxDtypeSpeedup);
    const dc = DTYPE_COLORS[dtype] || DTYPE_COLORS.float64;
    return <div key={dtype} style={{
      display: 'grid',
      gridTemplateColumns: barGridCols,
      gap: 10,
      alignItems: 'center'
    }}>
                    <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: 6,
      minWidth: 0
    }}>
                      <span style={{
      display: 'inline-block',
      fontSize: '0.72em',
      fontWeight: 600,
      padding: '2px 8px',
      borderRadius: 999,
      background: dc.bg,
      color: dc.text,
      whiteSpace: 'nowrap',
      flexShrink: 0
    }}>
                        {dtype}
                      </span>
                      {!isMobile && <span style={{
      fontSize: 11,
      color: colors.mutedText,
      whiteSpace: 'nowrap'
    }}>({count})</span>}
                    </div>
                    <BarTrack>
                      <HoverBar tip={ratioTip(avgSpeedup)} width={`${widthPct}%`} color={chartColor(avgSpeedup)} rounded isDarkMode={isDarkMode} />
                    </BarTrack>
                    <div style={{
      textAlign: 'right',
      fontWeight: 600,
      fontSize: 12,
      color: colors.text
    }}>{formatRatio(avgSpeedup)}</div>
                  </div>;
  })}
            </div>
          </div>
        </div>}

      <div style={{
    border: `1px solid ${colors.border}`,
    borderRadius: 10,
    background: colors.mutedCardBg,
    marginBottom: 20,
    overflow: 'hidden'
  }}>
        <button onClick={() => setIsMetaOpen(v => !v)} style={{
    display: 'flex',
    alignItems: 'center',
    gap: 6,
    width: '100%',
    padding: 14,
    background: 'transparent',
    border: 'none',
    cursor: 'pointer',
    fontWeight: 600,
    fontSize: 14,
    color: colors.text,
    textAlign: 'left'
  }}>
          <span style={{
    fontSize: 10,
    display: 'inline-block',
    transform: isMetaOpen ? 'rotate(90deg)' : 'rotate(0deg)',
    transition: 'transform 0.15s'
  }}>▶</span>
          Benchmark Details
        </button>
        <div style={{
    maxHeight: isMetaOpen ? 500 : 0,
    overflow: 'hidden',
    transition: isMetaOpen ? 'max-height 0.3s ease-in' : 'max-height 0.3s ease-out'
  }}>
          <div style={{
    padding: '0 14px 14px'
  }}>
            <div><strong>Generated:</strong> {meta.generatedAt || '-'}</div>
            <div><strong>Source:</strong> <code>{meta.sourceJson || '-'}</code></div>
            {meta.runtimes && Object.entries(meta.runtimes).map(([rt, ver]) => <div key={rt}><strong>{rt.charAt(0).toUpperCase() + rt.slice(1)}:</strong> <code>{ver}</code></div>)}
            {meta.pythonVersion ? <div><strong>Python:</strong> <code>{meta.pythonVersion}</code></div> : null}
            {meta.numpyVersion ? <div><strong>NumPy:</strong> <code>{meta.numpyVersion}</code></div> : null}
            <div><strong>numpy-ts:</strong> <code>{meta.numpyTsVersion || '-'}</code></div>
            {meta.machine ? <div><strong>Machine:</strong> <code>{meta.machine}</code></div> : null}
          </div>
        </div>
      </div>

      <h2>Detailed Results</h2>
      <p style={{
    color: colors.mutedText
  }}>
        Higher is better. A speedup over <code>1.00x</code> means <code>numpy-ts</code> was faster than NumPy for that benchmark.
      </p>

      {categories.map(category => {
    const isOpen = !!openCategories[String(category.name)];
    const benchmarks = isOpen ? Array.isArray(category.benchmarks) ? category.benchmarks : detailMap?.[category.name] || [] : null;
    return <div key={String(category.name)} id={`cat-${String(category.name).replace(/\s+/g, '-').toLowerCase()}`} style={{
      marginTop: 18,
      border: `1px solid ${colors.border}`,
      borderRadius: 10,
      background: colors.cardBg,
      overflow: 'hidden',
      scrollMarginTop: 80
    }}>
            <button onClick={() => toggleCategory(String(category.name))} style={{
      display: 'flex',
      alignItems: 'center',
      gap: 6,
      width: '100%',
      padding: '12px 14px',
      background: 'transparent',
      border: 'none',
      cursor: 'pointer',
      fontWeight: 600,
      fontSize: 'inherit',
      color: colors.text,
      textAlign: 'left'
    }}>
              <span style={{
      fontSize: 10,
      display: 'inline-block',
      transform: isOpen ? 'rotate(90deg)' : 'rotate(0deg)',
      transition: 'transform 0.15s'
    }}>▶</span>
              {String(category.name)} ({category.count} benchmarks, speedup {(Number(category.avgSpeedup) || 0).toFixed(2)}x)
            </button>
            {isOpen && <div style={{
      padding: '0 14px 14px'
    }}>
                <div style={{
      fontSize: 13,
      color: colors.mutedText,
      marginBottom: 8
    }}>
                  Slower than NumPy: {category.slowerCount} | Faster than NumPy: {category.fasterCount}
                </div>
                <div style={{
      overflowX: 'auto'
    }}>
                  {benchmarks.length === 0 && detailLoading ? <div style={{
      padding: '20px 10px',
      color: colors.mutedText,
      fontSize: 13
    }}>Loading benchmarks…</div> : <table style={{
      minWidth: '100%',
      borderCollapse: 'collapse',
      margin: 0
    }}>
                    <thead>
                      <tr>
                        <th style={{
      textAlign: 'left',
      padding: '8px 10px',
      background: colors.tableHeadBg,
      color: colors.tableHeadText,
      borderBottom: `1px solid ${colors.tableRowBorder}`
    }}>Benchmark</th>
                        <th style={{
      textAlign: 'left',
      padding: '8px 10px',
      background: colors.tableHeadBg,
      color: colors.tableHeadText,
      borderBottom: `1px solid ${colors.tableRowBorder}`
    }}>Speedup</th>
                        <th style={{
      textAlign: 'left',
      padding: '8px 10px',
      background: colors.tableHeadBg,
      color: colors.tableHeadText,
      borderBottom: `1px solid ${colors.tableRowBorder}`
    }}>NumPy ops/s</th>
                        <th style={{
      textAlign: 'left',
      padding: '8px 10px',
      background: colors.tableHeadBg,
      color: colors.tableHeadText,
      borderBottom: `1px solid ${colors.tableRowBorder}`
    }}>numpy-ts ops/s</th>
                      </tr>
                    </thead>
                    <tbody>
                      {benchmarks.map((b, idx) => <tr key={`${String(b.name)}-${idx}`} style={{
      background: idx % 2 === 0 ? 'transparent' : colors.tableRowAlt
    }}>
                          <td style={{
      fontFamily: 'monospace',
      fontSize: 12,
      padding: '8px 10px',
      borderBottom: `1px solid ${colors.tableRowBorder}`,
      color: colors.text
    }}><BenchmarkName name={b.name} /></td>
                          <td style={{
      padding: '8px 10px',
      borderBottom: `1px solid ${colors.tableRowBorder}`
    }}>
                            <span style={{
      background: ratioBg(b.ratio),
      color: ratioColor(b.ratio),
      padding: '2px 8px',
      borderRadius: 999,
      fontWeight: 700,
      fontSize: 12
    }}>
                              {formatRatio(b.ratio)}
                            </span>
                          </td>
                          <td style={{
      padding: '8px 10px',
      borderBottom: `1px solid ${colors.tableRowBorder}`,
      color: colors.text
    }}>{formatOps(b.numpyOps)}</td>
                          <td style={{
      padding: '8px 10px',
      borderBottom: `1px solid ${colors.tableRowBorder}`,
      color: colors.text
    }}>{formatOps(b.numpyTsOps)}</td>
                        </tr>)}
                    </tbody>
                  </table>}
                </div>
              </div>}
          </div>;
  })}
    </div>;
};

export const benchmarkData = {
  "summary": {
    "avgSpeedup": 1.1125,
    "medianSpeedup": 0.9939,
    "bestCase": 2422.8189,
    "worstCase": 0.0942,
    "totalBenchmarks": 7159
  },
  "meta": {
    "generatedAt": "2026-05-15 01:19:35 UTC",
    "sourceJson": "benchmarks/results/latest-full-small.json, benchmarks/results/latest-full.json, benchmarks/results/latest-full-large.json",
    "runtimes": {
      "node": "24.12.0"
    },
    "pythonVersion": "3.13.5",
    "numpyVersion": "2.3.1",
    "numpyTsVersion": "1.4.0",
    "machine": "Apple M4 Max (16 cores, 128 GB, arm64)"
  },
  "categories": [{
    "name": "creation",
    "avgSpeedup": 1.7568,
    "count": 639,
    "fasterCount": 476,
    "slowerCount": 163
  }, {
    "name": "arithmetic",
    "avgSpeedup": 1.0511,
    "count": 885,
    "fasterCount": 400,
    "slowerCount": 485
  }, {
    "name": "math",
    "avgSpeedup": 0.6155,
    "count": 375,
    "fasterCount": 82,
    "slowerCount": 293
  }, {
    "name": "trig",
    "avgSpeedup": 0.6053,
    "count": 648,
    "fasterCount": 151,
    "slowerCount": 497
  }, {
    "name": "gradient",
    "avgSpeedup": 4.481,
    "count": 66,
    "fasterCount": 66,
    "slowerCount": 0
  }, {
    "name": "linalg",
    "avgSpeedup": 1.4987,
    "count": 807,
    "fasterCount": 523,
    "slowerCount": 284
  }, {
    "name": "reductions",
    "avgSpeedup": 0.9624,
    "count": 1239,
    "fasterCount": 613,
    "slowerCount": 626
  }, {
    "name": "manipulation",
    "avgSpeedup": 1.1562,
    "count": 693,
    "fasterCount": 329,
    "slowerCount": 364
  }, {
    "name": "io",
    "avgSpeedup": 2.7096,
    "count": 187,
    "fasterCount": 162,
    "slowerCount": 25
  }, {
    "name": "indexing",
    "avgSpeedup": 0.6598,
    "count": 345,
    "fasterCount": 127,
    "slowerCount": 218
  }, {
    "name": "bitwise",
    "avgSpeedup": 0.6507,
    "count": 30,
    "fasterCount": 7,
    "slowerCount": 23
  }, {
    "name": "sorting",
    "avgSpeedup": 0.8207,
    "count": 225,
    "fasterCount": 58,
    "slowerCount": 167
  }, {
    "name": "logic",
    "avgSpeedup": 1.6874,
    "count": 426,
    "fasterCount": 242,
    "slowerCount": 184
  }, {
    "name": "statistics",
    "avgSpeedup": 1.5367,
    "count": 78,
    "fasterCount": 48,
    "slowerCount": 30
  }, {
    "name": "sets",
    "avgSpeedup": 3.3274,
    "count": 99,
    "fasterCount": 77,
    "slowerCount": 22
  }, {
    "name": "random",
    "avgSpeedup": 0.9056,
    "count": 138,
    "fasterCount": 49,
    "slowerCount": 89
  }, {
    "name": "polynomials",
    "avgSpeedup": 2.0631,
    "count": 81,
    "fasterCount": 63,
    "slowerCount": 18
  }, {
    "name": "fft",
    "avgSpeedup": 0.9128,
    "count": 198,
    "fasterCount": 88,
    "slowerCount": 110
  }],
  "dtypeStats": [{
    "dtype": "float64",
    "count": 863,
    "avgSpeedup": 1.0225,
    "medianSpeedup": 0.9487
  }, {
    "dtype": "float32",
    "count": 713,
    "avgSpeedup": 1.0493,
    "medianSpeedup": 0.9822
  }, {
    "dtype": "float16",
    "count": 632,
    "avgSpeedup": 1.3611,
    "medianSpeedup": 1.3626
  }, {
    "dtype": "int64",
    "count": 587,
    "avgSpeedup": 1.0272,
    "medianSpeedup": 0.9434
  }, {
    "dtype": "uint64",
    "count": 563,
    "avgSpeedup": 0.999,
    "medianSpeedup": 0.9301
  }, {
    "dtype": "int32",
    "count": 611,
    "avgSpeedup": 1.1573,
    "medianSpeedup": 1.0537
  }, {
    "dtype": "uint32",
    "count": 566,
    "avgSpeedup": 1.1876,
    "medianSpeedup": 1.0721
  }, {
    "dtype": "int16",
    "count": 554,
    "avgSpeedup": 1.1138,
    "medianSpeedup": 1.0144
  }, {
    "dtype": "uint16",
    "count": 551,
    "avgSpeedup": 1.1245,
    "medianSpeedup": 1.0154
  }, {
    "dtype": "int8",
    "count": 554,
    "avgSpeedup": 1.2721,
    "medianSpeedup": 1.0168
  }, {
    "dtype": "uint8",
    "count": 557,
    "avgSpeedup": 1.2723,
    "medianSpeedup": 1.0452
  }, {
    "dtype": "complex128",
    "count": 204,
    "avgSpeedup": 0.853,
    "medianSpeedup": 0.7969
  }, {
    "dtype": "complex64",
    "count": 204,
    "avgSpeedup": 0.7977,
    "medianSpeedup": 0.6199
  }]
};

Benchmark snapshot comparing numpy-ts against native Python NumPy (OpenBLAS-backed) across small, medium, and large array sizes. Run your own via `npm run bench`.

<Tip>
  All benchmarks measure computation time from JS and Python, respectively. To learn more, check out [benchmark methodology](./methodology).
</Tip>

<BenchmarkReport data={benchmarkData} detailUrl="/assets/v1.4.x/vs-numpy-benchmarks.json" />

<div style={{display: 'none'}} data-llm-summary="true">
  ## Benchmark Summary

  * **Average speedup**: 1.11x vs NumPy
  * **Best case**: 2422.82x
  * **Worst case**: 0.09x
  * **Total benchmarks**: 7159
  * **Machine**: Apple M4 Max (16 cores, 128 GB, arm64)
  * **numpy-ts version**: 1.4.0

  ### Performance by Category

  | Category     | Avg Speedup | Count | Faster | Slower |
  | ------------ | ----------- | ----- | ------ | ------ |
  | creation     | 1.76x       | 639   | 476    | 163    |
  | arithmetic   | 1.05x       | 885   | 400    | 485    |
  | math         | 0.62x       | 375   | 82     | 293    |
  | trig         | 0.61x       | 648   | 151    | 497    |
  | gradient     | 4.48x       | 66    | 66     | 0      |
  | linalg       | 1.50x       | 807   | 523    | 284    |
  | reductions   | 0.96x       | 1239  | 613    | 626    |
  | manipulation | 1.16x       | 693   | 329    | 364    |
  | io           | 2.71x       | 187   | 162    | 25     |
  | indexing     | 0.66x       | 345   | 127    | 218    |
  | bitwise      | 0.65x       | 30    | 7      | 23     |
  | sorting      | 0.82x       | 225   | 58     | 167    |
  | logic        | 1.69x       | 426   | 242    | 184    |
  | statistics   | 1.54x       | 78    | 48     | 30     |
  | sets         | 3.33x       | 99    | 77     | 22     |
  | random       | 0.91x       | 138   | 49     | 89     |
  | polynomials  | 2.06x       | 81    | 63     | 18     |
  | fft          | 0.91x       | 198   | 88     | 110    |

  ### Performance by DType

  | DType      | Avg Speedup | Median Speedup | Count |
  | ---------- | ----------- | -------------- | ----- |
  | float64    | 1.02x       | 0.95x          | 863   |
  | float32    | 1.05x       | 0.98x          | 713   |
  | float16    | 1.36x       | 1.36x          | 632   |
  | int64      | 1.03x       | 0.94x          | 587   |
  | uint64     | 1.00x       | 0.93x          | 563   |
  | int32      | 1.16x       | 1.05x          | 611   |
  | uint32     | 1.19x       | 1.07x          | 566   |
  | int16      | 1.11x       | 1.01x          | 554   |
  | uint16     | 1.12x       | 1.02x          | 551   |
  | int8       | 1.27x       | 1.02x          | 554   |
  | uint8      | 1.27x       | 1.05x          | 557   |
  | complex128 | 0.85x       | 0.80x          | 204   |
  | complex64  | 0.80x       | 0.62x          | 204   |
</div>
