1

Various source on the Web (e.g., http://www.prepressure.com/library/paper-size) specify the A4 paper size as 210 mm × 297 mm or 595 pt × 842 pt. Using 1 pt = 25.4 mm / 72, the width 210 mm ≈ 595.275590551 pt is closer to 595 mm than to 596 mm both in terms of absolute and relative errors.

The relative errors to the ideal ratio ⎷2 are |297/210 - ⎷2|/⎷2 ≈ 0,000051019 = 0,0051019 % and |842/595 - ⎷2|/⎷2 ≈ 0,000645226 = 0,0645226 %, respectively.

Now run latex followed by dvips on

\documentclass[a4paper]{article}%% either use the option a4paper or:
%\setlength\paperheight{297mm}%
%\setlength\paperwidth{210mm}
\begin{document}
Test
\end{document}

In the resulting Postscript file, we see

%%BoundingBox: 0 0 596 842
…
%%DocumentPaperSizes: a4
…
{ pop << /PageSize [595 842] >> setpagedevice }

The width of the bounding box is different from what the Web sources usually specify. Also notice that the relative error to the ideal ratio is |842/596 - ⎷2|/⎷2 ≈ 0,001033708 = 0,1033708 %, which is worse.

So why 596 and not 595? Any rationale? Is this still within the (coarse) accuracy of TeX or is there a bug there? Any chance to improve this?

Using Knuth's point, which is 1/72.27 in = 25,4 mm / 72.27 ≈ 0.351459804 mm, we'd arrive at the paper size of ≈ 597.507874016 pt × 845.046850394 pt, so I hypothesize that it's NOT Knuth's points which are meant in the Postscipt file.

PS. Looking into topoints(integer i) pointed out by David in https://tug.org/svn/texlive/trunk/Build/source/texk/dvipsk/output.c?revision=61701&view=markup, we discover that the code there, i += 65780L; return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176;, does not correspond to its comment. Namely, the code does NOT always perform ⌈i/65781.76⌉, as can be witnessed by i=1: the code yields (65781/6578176)·100 + (65781%6578176)·100/6578176 = 0·100 + 65781·100/6578176 = 0 + 6578100/6578176 = 0, whereas it should yield ⌈1/65781.76⌉ = 1. Overflows start with i=2147417868. If we wish (for whatever reason) to upround the results of the division, we have to mind this:


Let 𝑖∈ℕ₀, 𝑐 = 𝑔/ℎ ∈ ℚ₊, 𝑐>1, 𝑔,ℎ ∈ ℕ₊. Task: compute ⌈𝑖/𝑐⌉.

Claim: For integers 𝑑,𝑒⩾1 we have ⌈𝑑/𝑒⌉ = ⌊(𝑑+𝑒-1)/𝑒⌋.

Proof. If 𝑑|𝑒 then LHS = 𝑑/𝑒 = ⌊𝑑/𝑒+(𝑒-1)/𝑒⌋ = RHS. Otheriwse, 𝑑∤𝑒. Then LHS = ⌊𝑑/𝑒⌋+1 = ⌊(𝑑-1)/𝑒⌋+1 = ⌊(𝑑-1)/𝑒+1⌋ = RHS. QED

So ⌈𝑖/𝑐⌉ = ⌈ℎ𝑖/𝑔⌉ = ⌊(ℎ𝑖+𝑔-1)/𝑔⌋.


As 65781.76 = 1644544/25, we'd have to replace the function body with return (25LL*i+1644543)/1644544;. This requires long long from C99 and avoids overflow only if long long is wider than int. With a little more math, we can avoid overflow in C89 while using only arithmetics on int: http://stackoverflow.com/a/78127921.

However, I see no overly convincing reason to upround. For simple rounding of i/65781.76 towards the nearest integer, we have to compute the rounding of 25i/1644544, e.g., via return (25LL*i+822272)/1644544;, since the integer division / in C rounds down.

11
  • 1
    A4 is exactly 210 mm × 297 mm it is not that that is an approximation to the exact size based on root 2. Commented Mar 7 at 19:13
  • @DavidCarlisle In this case, the relative error is still bigger: |842/596−297/210|÷(297/210) > |842/595−297/210|÷(297/210).
    – AlMa1r
    Commented Mar 7 at 19:15
  • 1
    so it should be 595.3 but tex arithmetic is pretty inaccurate and actually its better to be too big than too small in case you clip stuff too tightly Commented Mar 7 at 19:16
  • Not sure about Postscript, but in TeX, 1pt = 1/72.27in (roughly, in fact 1in = 72.26999pt due to fixed point precision).
    – Skillmon
    Commented Mar 7 at 19:36
  • 1
    "so I hypothesize that it's NOT Knuth's points which are meant in the Postscipt file. Indeed, 1 TeX point \ne 1 Adobe point (aka "big point", or bp). TeX uses the convention 1in=72.27pt, whereas Adobe (who created PostScript...) uses the 1in=72bp convention.
    – Mico
    Commented Mar 7 at 19:39

1 Answer 1

5

This is a non answer but too long for a comment.

Assuming you have a site default set to be A4 the test document produces

pdflatex: Page size: 595.276 x 841.89 pts (A4)

latex/dvipdfmx: Page size: 595.28 x 841.89 pts (A4)

latex/dvips/ps2pdf: Page size: 595 x 842 pts (A4)

So you see, the issue is with dvips rather than latex.

As latex has not specified a page size, you get the site default which comes from a file installed something equivalent to

/usr/local/texlive/2023/texmf-dist/dvips/config/config.ps

which says

@ a4 210mm 297mm
@+ ! %%DocumentPaperSizes: a4
@+ %%BeginPaperSize: a4
@+ /setpagedevice where
@+  { pop << /PageSize [595 842] >> setpagedevice }
@+  { /a4 where { pop a4 } if }
@+ ifelse
@+ %%EndPaperSize

so the 595 is asserted and you see that at the end of the ps file (and that gets used by ps2pdf which is why the above shows 595 exactly)

which still leaves the question of where the 596 in the bounding box comes from...

Ah the comments in the dvips.c source (output.c) say

/*
 *   Convert scaled points to PostScript points.  This is the same
 *   as return (i * 72 / (65536 * 72.27)), which is the same as
 *   dividing by 65781.76, but we want to round up.
 */

and 596 is 595.273 rounded up....

in theory you can change this with

\special{papersize=592.48pt, 841.89pt}

but I can't make it give 595pt it jumps between 591 and 596....

7
  • (1) I'm unsure why the authors would want to round up. If the page size is clipped per later PostScript command at 595 pt anyway, there's no point in offering a larger bounding box. Or is there? (2) The actual code is a bit complicated. I'm unsure why, after i += 65780L, they return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176, as they could simply say i/65781.76f (which might be imprecise, but it's usually way more precise than TeX's own computations) or 100LL*i/6578176 or, better, 25LL*i/1644544. Perhaps, avoiding overflows and staying precise?
    – AlMa1r
    Commented Mar 7 at 22:34
  • @AlMa1r the code in the C and the config code to overlay the page size from the config may well be different people decades apart. this is all very old (and I didn't trace it all which is why I put that not an answer banner at the top) but it may help someone track further, Commented Mar 8 at 0:26
  • For uprounding, i += 65780L; return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176; is wrong. Running it on i=1 yields (65781/6578176)*100 + (65781%6578176)*100/6578176 = 0*100 + 65781*100/6578176 = 0 + 6578100/6578176 = 0, whereas the result should be ⌈1/65781.76⌉ = 1. Overflows start with i=2147417868. A trivial repair would be replacing the procedure body with return (i*25LL+1644543LL)/1644544LL;; this assumes long long from C99. However, I'm unsure what uprounding is good for. Without such knowledge, I'd suggest rounding to the next integer: return (i*25LL+822272LL)/1644544LL;
    – AlMa1r
    Commented Mar 8 at 4:04
  • Perhaps, there might be a mathematical reformulation of this that requires neither C99 nor risks an overflow from multiplying by 25. As for who wrote this, the earlierst commit to the tug repository is from karl, whoever he might be (Karl Berry?): tug.org/svn/texlive/trunk/Build/source/texk/dvipsk/… .
    – AlMa1r
    Commented Mar 8 at 4:22
  • @AlMa1r yes Karl Berry, but I think this goes back to Tom Rokicki 15 years before that commit. Feel free to edit this answer, comments like the above are easy to miss if left in comments. Also you could raise a bug at texlive (easiest way is to mail tex-live at tug.org) Commented Mar 8 at 9:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .