Как работает arctime в Metapost?

Как работает arctime в Metapost?

Пожалуйста, посмотрите на следующий код Metapost:

path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
draw p;
show len;% 2799
show s;% 2.92...
show t;% 2.67...

Почему s и t не одинаковы? Когда я добавляю длину дуги, ничего не должно меняться, я думаю. Где ошибка?

Редактировать: Я использовал версию 2.02 отсюда: http://www.tlhiv.org/mppreview/

This is MetaPost, version 2.02 (TeX Live 2023) (kpathsea version 6.3.5)  28 APR 2024 02:47
 **preview.mp
 (/usr/share/texlive/texmf-dist/metapost/base/mpost.mp
 (/usr/share/texlive/texmf-dist/metapost/base/plain.mp
 Preloading the plain mem file, version 1.005) ) (./preview.mp
 >> 2799.0210591829564
 >> 2.9211035593209118
 >> 2.6795082428530486 [0] )
 1 output file written: preview.mps

решение1

Я не утверждаю, что полностью понимаю, что arctimeделает и какой алгоритм используется для его вычисления. Проверка исходного кода MetaPost в файле mp.w(вы можете попробовать скомпилировать этот файл CWEB в PDF с помощью cweave, но некоторые _s не имеют префикса, \_что приводит к ошибке при TeXed), раздел 405, «Операции arclength и arctime основаны на рекурсивной функции, которая находит длину дуги кубического сплайна по заданным dz0, dz1, dz2...», а фактическая реализация — это функция mp_get_arc_timeв разделе 419.

Прочитав эти разделы, я понял, что это arctimeреализуется путем нахождения нуля с использованием двоичного поиска по числам с плавающей точкой (или с фиксированной точкой) для реализации обратной функции mp_do_arc_test().

При использовании MetaPost в командной строке с 32-битной фиксированной точкой по умолчанию (т. е. масштабированной), epsilon = 0.00002.

Thehttp://www.tlhiv.org/mppreview/использует double, который устанавливает epsilon = 1.52587890625e-05, и все другие системы счисления используют похожие значения.

В разделе 419 говорится:

Если arc0 больше длины дуги циклического пути h, результатом будет значение времени, большее длины пути.

где arc0— числовой аргумент, предоставленный arctime.

Используя измененный пример из вопроса,

path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
show len;
show s;
show t;
show epsilon;
show arclength subpath (0,t) of p;
show len+2500;
end;

Используя масштабированную систему счисления по умолчанию:

>> 2799.02077
>> 2.92111
>> 5.92111
>> 0.00002
>> 5299.043
>> 5299.02077

с использованием-numbersystem=double

>> 2799.0210591829564
>> 2.9211035593209118
>> 2.6795082428530486
>> 1.52587890625e-05
>> 2200.7155501530865
>> 5299.0210591829564

Мне кажется, что это t=5.92правильное значение, которое соответствует этому описанию, и результат можно интерпретировать с помощью t = s + l, где l- длина циклического пути p, которая равна 3. И, кроме того, это соответствует описанию MetaPost Manual о поведении, в arctimeкотором говоритсяarclength subpath (0,t) of p = a

Поэтому весьма вероятно, что t=2.67...результат указывает на ошибку, вызванную добавлением разных систем счисления.

решение2

Дальнейшее обновление: команда разработчиков опубликовала исправление в репозитории. Я вытащил его оттуда и собрал локально, и он выглядит хорошо. Используя пример, вставленный ниже, я теперь получаю это:

> mpost b.mp
This is MetaPost, version 2.11 (TeX Live 2025/dev) (kpathsea version 6.4.0/dev)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.02077
>> 2.92111
>> 5.92111
>> 3
>> "scaled" [1] )
1 output file written: b.1
Transcript written on b.log.

> mpost -numbersystem=double b.mp
This is MetaPost, version 2.11 (TeX Live 2025/dev) (kpathsea version 6.4.0/dev)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829564
>> 2.9211035593209118
>> 5.9211035593209118
>> 3
>> "double" [1] )
1 output file written: b.1
Transcript written on b.log.

и аналогично из других числовых систем. Это исправление, несомненно, войдет в стандартные дистрибутивы в свое время.

Отвечая на первоначальный вопрос

Оператор arctimeв MP возвращает время tна пути, когда arclengthпуть достигает желаемой длины в пунктах PostScript.

Итак, если p— путь, а a— желаемая длина, то arctime a of pдает время t, такое что arclength subpath(0, t) of p = a. При обычном использовании следует убедиться, что желаемая длина aнаходится в диапазоне от 0 до arclength p.

Но если путь pоказывается циклическим, то вы можете указать большую длину. Это похоже на то, как вы можете ссылаться на point 9 of fullcircleи т. д. Если вы изучите исходный код, вы увидите, что MP специально предусматривает, чтобы желаемая длина была больше фактической длины циклического пути. Алгоритм работает по пути точка за точкой, и если он возвращается к началу цикла, он выполняет вычисление, чтобы сократить остальную часть процесса (если вам действительно нужны подробности, вы можете изучить исходный код).

Реализация этого расчета вызвала ошибку в новых системах счисления, и теперь она исправлена. Спасибо команде разработчиков за быстрое исправление.


Обновлять: команда разработчиковподтверждатьчто это похоже на ошибку, вызванную использованием неявной целочисленной математики в исходном коде MP.


Это действительно комментарий, но разделы файла журнала слишком длинные, поэтому я отвечаю на него.

С текущей версией MP я обнаружил, что ваш пример дает ожидаемые результаты со старой scaledсистемой счисления. Но "неожиданные" результаты с любой из трех новых систем. Похоже, это то, о чем стоит сообщить команде разработчиков.

Если я добавлю пару строк к примеру OP, например так:

beginfig(1);
path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
draw p;
show len;% 2799
show s;% 2.92...
show t;% 2.67...
show arctime arclength p of p;
show numbersystem;

endfig;
end

Затем я получаю этот файл журнала, если запускаю с mpostиспользованием системы исчисления по умолчанию:

This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:56
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.02077
>> 2.92111
>> 5.92111
>> 3
>> "scaled" [1] )
1 output file written: b.1

Но если я использую любую из трех других систем счисления, я получаю "неожиданное" значение tfirst reported. Так что, по-видимому, что-то идет не так при вычислении arclengthциклического пути с использованием новых систем счисления.

:!mpost -numbersystem=double b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829564
>> 2.9211035593209118
>> 2.6795082428530486
>> 3
>> "double" [1] )
1 output file written: b.1
Transcript written on b.log.
"b.log" 12L, 389B    

:!mpost -numbersystem=decimal b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:58
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.021059182955437254465959453077
>> 2.921103559320912153438877894997069
>> 2.67950824285304864431956913069307
>> 3
>> "decimal" [1] )
1 output file written: b.1

:!mpost -numbersystem=binary b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:58
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829554372544659594531163
>> 2.9211035593209121534388778949970568
>> 2.6795082428530486443195691306930351
>> 3
>> "binary" [1] )
1 output file written: b.1

По моему опыту с MP, старая scaledсистема почти всегда лучше. OP может попросить владельца превьюера на thiv.org использовать систему нумерации по умолчанию, если иное не оговорено особо.

Связанный контент