diff --git a/benchmarks/data/roundmarker05px.kpp b/benchmarks/data/roundmarker05px.kpp new file mode 100644 index 0000000000000000000000000000000000000000..1e84e5b65df1b393ad5087cd718db1fdcdafd38d GIT binary patch literal 16157 zc$|frbz4;5_xJIGpvaKY-6hSy(A_Zf5Yi1wcL)gRP|`ifkP<@*NF&0~Au-Y=CDPq> zkKf+|xaYd&oIlRlarWAKt@ms16{Dl2g7<>z1qKENo|>wn9{N7;@BbVdeXTOChNEvd z9;znZ7#R3H|Nc+XU*S_@U_7x8GBEb>@Ur)|_rbsrjqgb7(n9hBpq5{T<1u&reosT@ zTWJa9bAE+?C~-b{O#o?7vtwrn2%7wc`GG25!bAP#`RU=6KTXwhN-#q~cg(Eip2H6% zKe6Q{4)gcVfh3d7WAB($O|p$-wN;t$ned)MhFKAlvAB^MJpY{{mWZgiHj1K)y4bR{ zXHfA5268P+eYydPoga+}`6sJ}j!C+3nAJFx-n~!xN^LrI&Ep%}Cn|eTWmGCrTooClkOQM`oFk&lLZre*?->`%2Z+BdTYH=07FF0R03Myqc>BX1&>`3 z%73}ZrN>V{IUT_*fI49kKd7dWFl7hVA8=U?<7S6Jxb7 zIeq)^sy^@j>RVcgGgZ*pU(Z*+=mt}*_uAT;AZcnVg z{Qo?VeVicpEmn{_Kc{v0&Mj7j=n-=9xOeO`PCWpUQ!t+a`rZ%L=#h{@AYXFN`i@B^ zs0WO!R&0U5c>YhV+#IK$5FBN@RBqYNAO@sh5WfrcDF4TTf#{}77VT#p;gZ-eXlr%Z zPzqvTFg1(CIGJ6*-el5XYB}>&Yy`qNt2$9etn1<(2}*H-BuM+D0o|&U2XoWxb+Gx2 zfxQ--Z9`3yE{Y{bcy$NH{i1v*rS**h&v8g>VLpQDrw6x8SnU4o-;9q41V`)(ju5w# zr|1egCRDX2{*dAMLUhxyOh|~U|9psh+ufUf^`C$*VvKO>M2or67bXiH@xx?g>LE!LT@uZO-jip|NCD`6K7tFpq?3*{=+L{f zCKZ@rHH&{>HR9n1m67Vo`}`a1aFt4#0g`o>Qs084Ez5pq4kGZvotG%8ezjA_631LP z72)C8`{yQwWl<;n;~CwnI(`OiTUe_c2<#HZfqxqSm4I7`yE!u0C%@#`8kenYE*a2Y z8;unlQ;QIu2#V=^O<0pDiWF$vvJI5Z*tKmCi=Dsl|5CsaBC}~)aLLdl8;}4+5GvQU zJPb@(J|a)<+(l+Gi*-4W)hP&W9THNMpT`~JgB?^x!am@H%Ae(vf)Id2iAXKPgxKAX zn{WB+cS&|*vt*ZP^Y4Y!*wB5eK+MI75375hR<~b49cw(F+4`UqQD?N;h52O&AkFpV zvMe25$FtRZ^{ER%u2r$_Ug0Zkwe=(f*Mu)7WM%^ICF=aBU+8WdCvsbj zoXZ5B$mLCVja#<+0_8c5hq-X-iOn3*GGbo%{x#dZ2~F}->PdbE9FU#o2T=A4ZJXC+ zFkUZeh!V;dFsv-}DVK{P*YSFS_I3p<0asFWK@WW1i`gTYXlLRo_M+xv$v28ylS)jHu7HPFEd?TK*zLwCJRn7MZj?7(I@Y`D$ z-|MG{4mj{NM*$ax;Dyos<$F@g%d+sN7YGB0TC%;Jrz(}3stC1+5xH6CZR+Sbs|ihE z4jHl@#8g11{q_C{x@)a;2OiwW@yCDEi?$X8e^Nnchk(Q%L(aitm(@7O`9xt(pf zQWg1LaO?>`H|_$xjTmpMeGxSjNJ!u>*-HudYDR#pv)8Nfr&9*;0L@p#qMJV05RBMM zO9W4Ui+?l6$Hg(3hTzV3R&*+({tKP^n9v42Avs#ZQ#2^=p(d}%tmKucZD~)kH}zEA zZSC_4Q7)|!yX_AX5)Y2tzy6yMkJxsCGU8j2ukF$QpvIoO=Oob5)p6johsR8M!jgI! zC*E}3oX7`cPDMz9^ULLQ8w=7RfO_=){N40pwa*kZ7vw-Z2Il>>=4RLKi0UGzc?%9d zq0E-NQn7b*QT2}IUyBfSe>q}l1BvxP!mw&vao)zti|odF|F4o*?E^F$4(VJhW+Nt+ z=CxNx8Rt`26K~{_*)V38-yhFuYlc0<&+&B%W#ty;h`@MLH!rL>^Q4VIc*;J%gdqwb zO{&0w9Yp?!H>K9KXe1+bm~6X6EU`CS;r5%aQu>yiu4f+=#pJ6sIQP~>(H-Q&zG zbZ&naVM(etDdS=?oKZ|2=jV5g>N-m^Ig{|LB@4-7+3Btq1P`V}ququBWzHV4edrYH z5yuOdTfV7Ci7R@fGPv=x65^_<3$x32vlrotXqYX7~3(JKrS}^CS=7#(CM1)io^K}E=D5$SsOSQ!>5mW~O z5i(-dq7t?~7qH{qJWmyUfsl&0y8W5HA^+Z+`1yPhJVc4@fa&zGH?|tf4R2NW2Bi`# zMfu6<8#$`VL0eDN-qWh`irBgVwIU29-3hR@PoqpvEo}oW=2seWf6*>CZ%Wj%2*(^K zsl=HhEuhuf^<$?ltG+2bS3+CD+a}WzgtY&9LN?b`H!Z*CpwsfiObe znwGoW6|={C_Tf{166c8RAb_@o=g9*7CoRkMD+QOZ_xsmO*HdSQsft76V131GV<8_O z{WDcWT~a|7{~6QRKx&!B(J9L^W!u=`r17Ut76GM<80wG?Vw|sMgxvv}+%x@@2}gZG zF76!47CyO4pAn;Cbu4Tad@+W&g`4fS9Sf;^Mi|AVx)4&-@*kR?9-ky=ghT^BuHz}D zJbWPb31C#anf8vZ<%*B|>1}p5_Bec_7l4nfqwIY6I5*bmeRCTokdwL90ewQCo{od(Kf{EUyPJ#Q~c4*Cvov$-?BXkNXt=0L~WQW6v8 zY{$aNc9UfGn7!L*uGhOCV9C9dEi7oqO4XMl{Yb$pejy*W3e9t6Ve{=>ts zanzezAc^zEGwu43+e(E>sWIL3;;$oOKUV}FZ)Ga^_&87`C@+fKhn_+7`n}%k5QXQuk-2I{|8aQu21)jS{n~j1%VJVLkv)8+RfJpQ z0|aR9q6ABbLx*B&?Y3hWk}C`GCaXFM1h;8{fA(6Y>d_baL^d`ri{UAYNMQoUWO!FU z+~m3bOlCEPkNw@lt9fWSrzu&F4Gll>F}v>=H$=X!gXMbd9jMp3&1Y3F1j1TVUOo+E zYrE|d$xODaPb|3&iAC77NJr9+jsJx2(*~G;-^S5ga>mJENxEY?S8$jpw_DV;v|AlN z@azub#&Y-8(kRy~^WSdzm&n`?9c}EX1t#3CG3L6*W1EBcxofd3g~(r1NT#Z7Gn*NOi1!e12&O@$*Rw8oAZ zIPz;z{^3hz$`wk|R^r`AoteVmu&u;YygpM&_>Qhuowb|0C#@}Lob-!>`+AEUnYB~%l>4@UL@D{T)b0RH^E*2qjU!A4t7p3D-!9WL9bvXU9?&h zBR|p618^(h*B4B~3QvC~HX>EWVdZ_E{QE}Fu*&6b4hNZP6cIH9)cLkvZg_t65D-eI z_=nCOo(z4`b(iAQ@gCbH?8ns}UQzu_AH=ay>l<^LNf)NVPv%M}awSt1bZ}D5Vw&tH^tHbHDco#DcO{0sRpLMPpJyl7uR*4Dpp_Xdffm$&@s* z8?sW=Z@XINo#cnhJNERWc0+r~h(0>BwWzG1+e#M=BG5A;Re}*#kx59l(iNdV0BuWK z35$OZdqvd=yi(JpSaGJ&(hc#P_=!KTkM@)J=B#x4&M~W~4Z-9%FoLFPK(9`;klU+Z zW;KW+Bhn#@<4s=h*_9W~muF9k3BhU^eRiITjM?{3b02g#c-1DG{+0eBsztyQOs|xY zQi-)0mi(m*5xbA)@lH&yu)O2+?=eJF9n;yVET`%j8faR%uxcvztwiNHpbDY0bW(KD zMLoZ3p7^6&dXmA8nwd+_B9iEa(zyWDP z-RSeby`-lEVRD!-XKPhwC#2ug$akmfUdii%geEOqr6fYXwfux(^~6UkBZa!w)k1Wl&)-Y ztZ~&}M>tz0?=q$pTCUp{P_{nL4AbHD`W)X)29ErXBerqs_TZLYn{G`?U&j{{bzb|7 zdGYuu%5MN=JfL1lp*ZSM~ut69G)NQe%V9UnHV{u z^iLkfQ)+6VY3W3iEzve&S7Vx-o}b6jbYBomvVZ$=9KBrSmxCoJ=R=|s1`|U(qz;x66GV`<)(ASevc?vN4T_M*z)4^JLy^+GZuO3V#Y zmt@YorYtrB!BJ-at;nAtDwzD}hH4v8e*be!|0SG5uiv!Uq>LrdESb%wCjX$y zmR_Dt-XP*2(cP1Ii$D2j}FVL~vHGJ!LW#vO=;d7t6FT2~oAH&)-L@ z#c!Sne1Q&Z-5;Y(<6PL5e>skp&H8l9ftjU{)vFD!2JPkGY{jck$z-XIh?}!SLlOf> zZ-e>bDh29%98Z672th$(U~rzCInfhbk{%uMp5U>{ETr<$AFWKV!4ytq3% z-UWtl8RT<^|3{!GKlG369(GBDWKfUe}W&r)5Ps zU17ACj7Gqq``1_X`hB~sU2FgLxrS2^++{-%cJ(&r$C!as_3Z&FwatoCzG%(rWZ+qj zXiX^DC4kRJaA9tX*G|UGqGjcoa3D>x(i3M2LNm)k1T4uk(sh!}Us2~fy=h;8qmx3O zg0@a3t34b?yVg6Pt)}Mf4kD#RQ9ao{El`%036~2Jnd-iJH+b6Bg?)#E90`JNEv0;woMs@F=<@7 zT{Rw?7}+}#4mv1NK{x)v%L1XsJC)0jDiuBZ()o)hG_1PKJEa&L9=&hCHc7`q6Jsx< zS}oD)FhrBTlX#LC^|FqoWWc*`l-f+`UWC@Ig|D#eMQnA!P@$Zui<6YIpt*foh-cspK&lun>@wXK!?rv-LD>S*Z4}Ri)VPYAy;jB(v zttRqzI&%wcRao^ph@E3u_D{)eeBXk{XYBvHhz-c~-lkHPg5yi5fnem#$!G3_tWtNi z!lcdKU}(J%w6q3ImN@>RWXr`%{-NCNlY1+_!4O{@Z<7~zy&htjxN^9Y{IjP|eYbEf z!tCB!#oy_WU?J=HT}zok<9_19h?0WFb!wzQBj|^Zd6!Y;Zp8k_oJ;w)nfs$=8=QeO zL^YW%)iQNASK(+4vZ33vwq$9b#2Ac61uH4q#UAB>Z%;5tsZ$RLgPFO~5dq&DWr|g8 zeUJ=s3e9C|$fT)$Zv#jX*NY@6U~&#u-Z_hkGecWTbRorTH6NP-HAfr`1Z8Y#k)-tG z_>ESwqTMQ#8^3($vrACKX7uEyYeApF#L^`g^ThC#ch{9MshB;Z7ZeEiFg_N>ySYF_inKF17O#&$4YiFb%o5?Ci0 zTHWti02G?q;(G7<8T|hOipfAB*f9lDGNgl5coVOrF=||6TJvVbj;jks0^NEh#q%lVneAaYg~t z0$?%UWw*^UNsK*_EXkRY9S#UppwtaEB82PoUB@{F-n>>Lc2S+yNG=_inW0Sh$mo3Izsk~rGQiDrkgSylMyssVndmD9sake_IC6;PhJa+%NiP-gjWNdy=rGggg z%GNgT%mV39vf@-Zh{EKiv=VCLjQGu<*#|;@U>E(E;)9h5MFuNE1Iqa6KA(msj}cal zn^jBr{H>-(j&;ByKSm?_8EE}o1 zC-aro4qiDs-f?Woi%1r2UXPtZEDmk>gO?D2ZmjO5JNDsVzez^^T>4C%rr?kA!K zN>Eldv?d}P^5QoqA0~gNT@`K&Pb}FjYgP3j-OSha4)|ezeh@sGMeEo6)#Y;+VVEQ` zZ)D@IiefU$hOT0A-!J>Q{f&3-r=p)YT*eN?@9p6Vn8R_6L)TBzu$LMzHh+HJFrgTr zE6#DnLn|^8Fp#Wc;=|}(8W2!c@#Zay<*im@V+jYxeB;*Zx3B+kwUp(~slR7=bKtf*!2uUfpq-RhVpqGC8^>Ag)0 zk_Pi;U5ZnFF?;yRlA$`E9w>C2a53hIC@#(6b~5a`BueA6L!5XhKUo2IQ~2H{8-fFC z2l|bc;L)M;GQa*l*P-*f7|AhB>(7qX96l+j#WR*j-p<)EHN9#2F@)Lv)}`(I;xR)t0yq0`X8`c%?Qg{ zvnEgy9p5t$8=qNMVTuaT@G(vxP0Z-8Ueb!VOSGA(RTDFDbnD1&Sud;xj?O-D<8w%d zGQ8$#zB_%i^$uMA_dLp6yHFz~dSaUz%?vo0|4ziFRJyNy-5I1Tct3QfCv0ASvV2s8 zkQRH&nx{wDaA*W$ZXaW)2F;Y1E~ng{4( z05Vk$rDl0}j!s!V{<%4nF$s|@9no_M`{Ci&XXVFraR;t2y%Se{9s$5o3WMGFY6EI>RRmZ<6X{m+heUHd7N^_u8?>zvO?ye_pEf~NLi?>?MvvBk2f!s-5L0v z`v=9E(u0FEP}_hL^*{9Du_x!;0@^qo z;q9s}QcBFeiaT|GXV>aQNz%%6Rog9yM{11CL-PmfsNu*w_#S1yw}Lyv7=~q$C~MXx zR){unr36u-;Mm|=G?4I9no@@KEPhcvXheL>(@){mQA+_R$uTnOm6rWihQ{II1l8u( zguGjJo-8dL>N|CcQ$FY+`@4td_;@Fy8Fq6%7o0$*V$G0eWD~?0VAoqNI*+0pER-$N znfms7chaXEDQFdN1KZZ_6uiF%LG{-5#Qv`U?Sam}5AIm1-$6vq-4R{7P03z2NgYMdPjd_^=s`dbq%=H;@9I#J?>dc#l!c<>ylK0GCRl@ecPK)#3+rx&JW>|W}Yv^3W74%(kMhoB7>F# zA~u7{^xPE-NEJIic5_Z5F)(N){^bHNon!r$2ujN3ifg}bg6jJ-8bHX`WTcNzr&e0YgFa?+U!dxj?SY!LmKB~^vwn8Zdp`YN)8 zH^b~{Sr#ebduv}wOIv5ov4UdTj;`o7l<{?4y`vk4QdoZZs!eT@p+R1WDrWv2UH^u& zX8P7I$h8S;N#=>N-^KALNvTD3X)~_nrkq;yywzLaltF)YU`T{ z<*q8AWNUSmk&W5@^1Giyt3&Z!$1`WVB2vFGp%f1V{!S82-wG_X+GGpsrlCm}(ri1; zDg;-n{g82BgamvoQJb#ppIwU3jgfsHki8IZfT$(Muo+NcnG3z~4pD1p&p^5-9|6v- z)9qC{rs~i{KYZ?i&D?%W66O^lBNo_<9-S_K!_Pr6S2hHbKs*RUub6WpsB33UYPSM6 zqL=kJNR0|=E@r4p0;sR51K6kcCeh2sbP z?XVbn4OOq)M~zNl9S6xJe~Bji(L)troWKsek)(Iz-$8J|7>hrG7nb6_2y<$!#Qy5s z(?Rqn_C!iW&+76Hq-I%#_HJ4}BG>Ls4KwKny74fe`@a)P0VSmXZHsk$6^aZV?`X8W z(^yb;Ehp2)H__=?K{PT4_6$*bWX>dh5<{n*kH{PK=SgKSs07VASc?Mw`QLu_(T4C( ztJ%P~97x)dmMgu+Wx(s^re|}GO@tCdGhvUtJ2q`al9FQU8<}B(k|FU@G&aGJyfw2_ zKU^Uh%M3x1;CGX<7hVYnmUxBkYtlFZch)WZxKo* zkmOx5fED!9Nu1>yK5L8}=V>WlHqzP;pI-oqF450P^F#>66d-n-$3cT=NI+}#O1?2p zy=^hA6_1l)naf$8o)VKo0rYoCQ`=0X=YKXce`j@kz*CXP#Moq(I59_U@pv4T{jgYP zDq40kJWu}jxZSfNeD4n(L^ny95p6x)su!3B5LLF zBY6Xs7dU@16?a+VCx0jOeSWxjR@(VU9=W~uf3GzQ^}N}EBDe?El30w1Tr)PDKe^2Z zq*5YLMgWIWQ|akt@3R1C^Zk%J6%0X~UNM#8(ZUeN7hVX&3TGut*>{CKdnBkHrrI4e&jh0!#l8(y>pngepQ;Mb4BB}Zh7kx zo$jw^N{T447UM-rGivDP>iuIY8bO9o=7!y;-C8%7JE5~)?Bl>&Y_C}{^4nGFI*tz| zU9~iyyD0kUUHesTOt-NQ9CT~kmqs7ibkf|O8wh<`AV(Y+lLv6pZ5@TYiMc`)=Bw)O zAlhH`5I^k?Bz{><-m{8LqC^-CE@>{pf!Y_9y7 zXguj_jFX_TZEbtil4mTMx^lU;j54?BW@3+%FPw^C0=rSE>d*XAVl=t>FFVZc-!3l& zP720Ys=7Si-p6)K(45(Ydtu!`x%z5yy(kNwNYAbkd8_p6vTq7I`3Np3Gr+Db+HZL1 z6Cc(E%xQ!TDOcSp0=jZ72)qdMtFbcQ!uulZiwEQ& zy(0NCKlpio;KNe_>5d$}8>EsJ5_FAF6oAWETA38tcRT+s(M1;GmH11V*?>8R+BSe=5 zYHa#q9Kl_VC@iW6Zd5lTcE_U(X<;QLh}hhvJAz8SO}EgB>9kFAh@$Qf{wf|&^?88Z zcrdg4m#iOJNW4HQ{XbZq-&_* z6M&bawT&T(BbE)_c z2vcW$Z!_!?7R9Sh^};-@qVBQZOqH zZ+PD=^!a=1xd_}DdcTJJ1E*M&K!wbKyoooV-Y-46f{}VHJsy0K+|cK~cs!JTU$vp; z8)#=n>^=<|tlfm2xh2?&(KWJ1--{;}x+&B}L8cC_-}&cVYNhkXDUovFV9}cryA|`s zUIk}6{@OGoSJItI@a(77rqtA?fVcOZyt8Hqu5RJttWN`)r7ArE>*K~hU+8V1^)Xk0 zq>&FQ`Few7lG?7lkb2esl_6$FFWLVkAN}-**uR~POcrHmTWoHF9-o`sEU)jWR{L{W z_ydYH3{Ay8vM|k6_Qv0+iG75%F5=fA5V3BrX@x825*YS90E?XnzsJRmqkBS#{4q`U z)Mp@JAH0{*xw&9K=sGv{`K1pnieKEEBuwz7nF}ga%f_ugvLVKNdg8jL3s&+3b?l+? za&eVnsm{XZ(KZb97=#{7Fu!@?>fR^R%7c~9jXIR0+cY{6Nr>4har)MBGSY8|H!whd zX06eG5i_PS3g_g_4ayuHyKMd+=XI~d_vp`V4X5aw81{QqU`g22=w3Bf5j$}D zLY{zCrrr>I2&XDx6^#|f8$P8R`RSpu=3T=4IlP40^xq+sGD{cKc*o;!M!Xb-&25C> zBkP5X^uE}GU5Kw%GOHfe1-paH$e&O z)9pQ*D}^_6xywJTA^Xt&uelwFc?Cdm`8J@qiiXUD3zw-|gCb*zltxm`{_ShiRR)x& z=fCaNmo0t^&-5V93@12gCdzdtFKaS4f>CYynlr%@_lXNq{dpk2Q_GcaIb$zpM~%{W zC&;cEILh4SvknUS3rpgCvdei%n=#OBrPG9j{- zWqoycPPj97O6e$kKQKZ2;Lqb#=!E&R8nGi5b<se8Czd`j2X18EH8t_ROg^6Mv7uJu~ZZ}F)a(V)tp%g zLgaeiahj)5=blaX#x{c$np^=U>9QG{79{w_=G6}=@b$a<@U5%P+%3^+yy3RECr$TyZWrO4dmoG8PuvdJ$x@DH4rx-*{s0UnUw{d%O(*NSJ5^)R=rRbOET&0}Gl5ibf|n=i)eLq3{CmTF?JFS*`)&ZCiz^5zXSM?9YWQp+*-rpFa-|Nl&N>TCwh4|`SZ)(NfBs! zf%eCKUWG4?1qC|IS2aNQqnilnARAjbxkR7nef5{e6EvC7YRf8gaA*CQ9Ch34=$L7s z5(`i+3GbVl0LHs~??p?J>Xip~c1W_zbXs5n!g&@x zcCMxs`mSWw4=}od|Ax6L_bB z9Do4Pn&6N{kr8|01VJ1oVq)sb{@i>O%k=ln#)s0Y$3Nwtqv#|376iuz*P}-ooT!Z4 zULRD~hSE1CDvU9n0K{HhTxd^cZWXUWTM_)+xQ_fb0VlD8yOyHY`*~L=lp9TvsmJ`B zwlfteu{{OR;@EvnLm)U#(pcv6NAY$L-L&AIEFUAfrEUJOs3aRBU(wH&p4T(~ zGS%WXuO&`^T@AFl3AA|w9_noCt|k}t>Q+OI3d=!c5CxPl>`z+B6NpgRQ0)08mI+B+ zHm(DqBflbu#|OD60!svlN3RM&bjN*ZQH`5*(OQs=!r0WFUrH@66FUhxUU0kytyz*{ z9Xot1M4++0-6AHw%kb8`4*Uk{$$#R}OmXf@_a_O=8pj-Qoo+z;P>~}j!jp46r(Ngh z%_g$hr|%Lrery?n2=m?|sYMh5Bes=wdv=Md$nDg6{s=PRVWMT8sPTFN+pqYjh@dnD zitb2`*sR5GdpzIDtdpS;8{Bi1947`rDVbIbUIubgJ=P!q5L`4QB$BzMI4p*!wr!Dq z2xxRoYmtWWl6%a51t2AjtCr6B_YZG~qX&1HhNBH}c^_}+(G!Rh5~VL@e+M&qydz&X za&N^kLN!i&%J8`xM$-MucWL8-MIrx-@CPx|J2noenJ2DBM)! zP2V<7xT2HWUw0+<0lE%**qAJs?@_PM#}Xo52R3_8Yy!-{w2O< zJ={@8&dohEUm6*vi;oq)K?BC-bFw6-Z#|-6e4twqmbYIeA?cg(wCA>67Whn!6+JmK zKW7@eZqLvW1bvXQfL{8U79z0$-t^)U4YEt3 zlHFuSn;FpSn&?R3R_mo%+<*if7V@mkYuU&`j)3*-;&h^re__vTbTGwu&u2y$lB}U8 z*wvL*nHiDxW7#l{yT8pFi{!wT!A61a_0R0i$GG0>6?wXvYENut<$uR|H!)p%ngPPu zEMajurVvsek5@sT#1eYs&%hYLNK5NQIOGjc7Fd>YguIuro%@r*aYSFeL zndGy}7%0C9S864JggxE>Q4$C@u1VeMX1teLZHB*D+v?hDz)kuWnw^*A>NJ&TSU4&slL%+|2FRWO)x%N#H zyE!;wpMTSwLFQ?yiD-z-{NIToOO9{`Ksd1q=KD5#rooI-pVv4<@(`xoC}Sro(R&;v z^C5RV*!uRJ0T3()aRH7Ndn(%2=6ap?y#F+y6aUbt14ZTuJ ziXK7AdOmkq4)(`CWxUhWbj9(U_j5R&wcVjxsq6w1K`~ODEI1+o>zpvg)St|G->xOy zE}j^G$#Z;LjVTaA^7zj)Zl5}IK?7Ka@@xncYTq{iph_8fX68Pxiu_Y#=<|zaN4(Jv z%S*CE=CNbbxImw;e? z20W`Lu+b^3jNL(VOV_CBKi5Gi3$wBYU=5j z6vy0^|HxoSV6B62wVmgEu}TF7TLkdKCX$m1QcLNwH~&Z zoj5p5;ncuvt)W@SC{dwNcNBHFLDc{pY_vC{SdsgN7ecQ`zZ2O!F$c|Fyn{N{45mZ_ z=aZD5blnjz@q64cwp#mIXU`|QN`<|v#^jaMj4X*EtfYOj=hyB3_bSyYYO1K3?nbs} zEoC>xtGWq!d!{NecNt9M(}JRl>Js`{S4;{l!mGFet$p>lZN9}HO9H`k z$SBpCi3EIZGPqwDTjtuf@-Ev!H}N(!$4*C-=wfdJv#P8{XY`jPrE^pW!rLz8NU)S% zLU6()iyqDi%BUwj6q-N3tRgc$c)y*4*XzVpYI6QC8c0YNH?@8|CmHm7k<#W#-C3D! z3ti+KdKr9e7iCOsN1!cyK801X9$sjLtcu|8nAj@{Gf#Myx5QzPwtp2PMS&KvOn3^0 z=8)YnkveDzk&uc+Lt=={;03W`k4(i7V--vhz6O!0E(jD{hQ*( zCtV4fiQqIkmFVF8;+4ub5IZ$Z@8fVFes-z5TG9Kd|H}|yuc3f<^wEB5V-$uQN~tHV zBkxtIFA%R$TDbCZ*5}8O3^Eo!Ia9K@0jk}2&NOTBj==^DE~3L&?EL7uU0>{zyP^+qMBISm5bIr1jbr=8zN_muK{})rvWYW))D}R(vj}>PQs2Mfm))S2VQAR_p14O zZdXnv=#^0 zID)=4ApJ(v#t3y@y-^ragM#3y=@X2r@)T-hDrtesIH*&IssJKzx-`~ zsYJWc7Uq0EC%9@D(IU{3v6BewzAuv6@A7-b1|FzSYeh@|TKI~$Rj9S3=|G3BbiIVP zOp$Yx&NMITzKzC8CU6W#AUIgW%(;91qCNnat7 z`~7#(>Son?K({dHd6w7++YU@2tT96Sdx*&Z|Gc6Q*Z`6#wxJ(F*R-w+*zl(7y-*48 zk`coL<>CiJNW9!lDoY!us+qtXr=ME6>DO1KaDcw3r8*NT|97ts-Xv`A9XZGM&qfku z?5-@yh(9+EEsiSRh3f5y_U*E+dTCK%<^S(+kf7&O2tZ^QcByjZd*!!xP^F^VNcUwS zjN^q`v^h>fsr=BpP0CID0=eWbDe3M;e;=;K)${GuG}|p=;~2mLYtc?EfBQUr^pBjy zkOGn0wD(2k9bTLLf4IS@aRX8%s+Vev;~s%(@V=~sI2rhwMo^LM=GHwMwimJpxU>AA z5d4?myna_pMuKf_k7D5KiJ^J}c1l0d>KnO+&o8V0Y^ZUc)V_(*eg#k!c{|BKXzfV6 z4tAJK-8)Mp(OsOi)in4%`l0*#AI7DRQ$anz1oZTKI#YP5g!+xI%rr)YFF^ZjG~nG@ z>tXm|B>~eVJ${ysAG*C(vKNR1c9H#rMNuma(${2S>jA^1=}J%1H&AbIZsy~xL$1S} zzFCF%CP=`3C!&|Jj+O>)P5UOsg_{?~t2XgJiJouWS&L06KNuGB;!Qt2)##oQwufsJ zpk895^t+6>m9!FxR(fR*f+K~&k=Vf2Ut`iXBA?6~sLXvKx}>JkRgwwiL+|pm-v)vk zOlZ#%|4SKF&*&fk*hzLBM`it-MwY>x8XB$l&F?eDWR5}zEY%D%5Zq1j;?_UVR5hJR zuNH{`L3v;^W7q57Z3Bk=CN>ks1;|X`CEW)7WG7|}`15pm8Q+kl5H;y4AZxsQ;ne4; z&8TXiMKPybP~fGto1Ol!q6cbu4i#}#&jVmYbBZE@=IOa2Uh9kIB^xS9Y zP0T~{hlE^K90Qn6*xeNVDU7D3*I$W}jR%WL_|slXtys`AAT2`7n62p*bK&U%n?7 z$G#~CmyjOzD|{i%13``BVGbX2U^8>OzjuSNgfqu8%cF!5OzhaP++Rk#2P?jTf8s3= z4K)Np3%P*t1I#|C4gDcKb6q*Zsfb?Tio`=KUH|5Sq(afE0@La!agq*dZ4p_#h5O2g dDS_XQ&vbY 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 m_startPoints; QVector m_endPoints; + QVector m_rectangleLeftLowerCorners; + QVector m_rectangleRightUpperCorners; + + void initCurvePoints(int width, int height); void initLines(int width, int height); + void initRectangles(int width, int height); QString m_dataPath; QString m_outputPath; @@ -62,6 +67,7 @@ inline void benchmarkStroke(QString presetFileName); inline void benchmarkLine(QString presetFileName); inline void benchmarkCircle(QString presetFileName); + inline void benchmarkRectangle(QString presetFileName); private Q_SLOTS: void initTestCase(); @@ -120,6 +126,15 @@ void colorsmudge(); void colorsmudgeRL(); + + void roundMarker(); + void roundMarkerRandomLines(); + void roundMarkerRectangle(); + + void roundMarkerHalfPixel(); + void roundMarkerRandomLinesHalfPixel(); + void roundMarkerRectangleHalfPixel(); + /* void predefinedBrush(); void predefinedBrushRL(); diff --git a/benchmarks/kis_stroke_benchmark.cpp b/benchmarks/kis_stroke_benchmark.cpp --- a/benchmarks/kis_stroke_benchmark.cpp +++ b/benchmarks/kis_stroke_benchmark.cpp @@ -52,6 +52,7 @@ //#define SAVE_OUTPUT static const int LINES = 20; +static const int RECTANGLES = 20; const QString OUTPUT_FORMAT = ".png"; void KisStrokeBenchmark::initTestCase() @@ -76,6 +77,8 @@ initCurvePoints(width, height); // for the lines test initLines(width,height); + // for the rectangles test + initRectangles(width, height); } void KisStrokeBenchmark::init() @@ -114,6 +117,32 @@ } } +void KisStrokeBenchmark::initRectangles(int width, int height) +{ + qreal margin = 0.5; + qreal skip = 0.01; + + qreal marginWidth = margin*width; + qreal marginHeight = margin*height; + + qreal skipWidth = skip*width >= 1 ? skip*width : 1; + qreal skipHeight = skip*width >= 1 ? skip*width : 1; + + // "concentric" rectangles + + for (int i = 0; i < RECTANGLES; i++){ + QPoint corner1 = QPoint(marginWidth + i*skipWidth, marginHeight + i*skipHeight); + QPoint corner2 = QPoint(width - marginWidth - i*skipWidth, height - marginHeight - i*skipHeight); + + if(corner1.x() < corner2.x() && corner1.y() < corner2.y()) { + // if the rectangle is not empty + m_rectangleLeftLowerCorners.append(corner1); + m_rectangleRightUpperCorners.append(corner2); + } + } +} + + void KisStrokeBenchmark::cleanupTestCase() { @@ -327,6 +356,52 @@ benchmarkStroke(presetFileName); } + +void KisStrokeBenchmark::roundMarker() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 40px) + QString presetFileName = "roundmarker40px.kpp"; + benchmarkStroke(presetFileName); +} + +void KisStrokeBenchmark::roundMarkerRandomLines() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 40px) + QString presetFileName = "roundmarker40px.kpp"; + benchmarkRandomLines(presetFileName); +} + +void KisStrokeBenchmark::roundMarkerRectangle() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 40px) + QString presetFileName = "roundmarker40px.kpp"; + benchmarkStroke(presetFileName); +} + + +void KisStrokeBenchmark::roundMarkerHalfPixel() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 0.5px) + QString presetFileName = "roundmarker05px.kpp"; + benchmarkStroke(presetFileName); +} + +void KisStrokeBenchmark::roundMarkerRandomLinesHalfPixel() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 0.5px) + QString presetFileName = "roundmarker05px.kpp"; + benchmarkRandomLines(presetFileName); +} + +void KisStrokeBenchmark::roundMarkerRectangleHalfPixel() +{ + // Quick Brush engine ( b) Basic - 1 brush, size 0.5px) + QString presetFileName = "roundmarker05px.kpp"; + benchmarkStroke(presetFileName); +} + + + /* void KisStrokeBenchmark::predefinedBrush() { @@ -462,6 +537,37 @@ #endif } + + +void KisStrokeBenchmark::benchmarkRectangle(QString presetFileName) +{ + KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName); + bool loadedOk = preset->load(); + if (!loadedOk){ + dbgKrita << "The preset was not loaded correctly. Done."; + return; + }else{ + dbgKrita << "preset : " << presetFileName; + } + m_painter->setPaintOpPreset(preset, m_layer, m_image); + + int rectangleNumber = m_rectangleLeftLowerCorners.size(); // see initRectangles + + QBENCHMARK{ + KisDistanceInformation currentDistance; + for (int i = 0; i < rectangleNumber; i++){ + QPainterPath path; + QRect rect = QRect(m_rectangleLeftLowerCorners[i], m_rectangleRightUpperCorners[i]); + path.addRect(rect); + m_painter->paintPainterPath(path); + } + } + +#ifdef SAVE_OUTPUT + m_layer->paintDevice()->convertToQImage(0).save(m_outputPath + presetFileName + "_rectangle" + OUTPUT_FORMAT); +#endif +} + void KisStrokeBenchmark::benchmarkStroke(QString presetFileName) { KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName); diff --git a/libs/global/kis_algebra_2d.cpp b/libs/global/kis_algebra_2d.cpp --- a/libs/global/kis_algebra_2d.cpp +++ b/libs/global/kis_algebra_2d.cpp @@ -350,12 +350,13 @@ int numSolutions = 0; const qreal D = pow2(b) - 4 * a * c; + const qreal eps = 1e-14; - if (D < 0) { - return 0; - } else if (qFuzzyCompare(D, 0)) { + if (qAbs(D) <= eps) { *x1 = -b / (2 * a); numSolutions = 1; + } else if (D < 0) { + return 0; } else { const qreal sqrt_D = std::sqrt(D); diff --git a/libs/image/kis_marker_painter.h b/libs/image/kis_marker_painter.h --- a/libs/image/kis_marker_painter.h +++ b/libs/image/kis_marker_painter.h @@ -30,6 +30,10 @@ class KRITAIMAGE_EXPORT KisMarkerPainter { public: + /// Any number bigger than this or lower than -this is considered invalid + static const qint32 ValidNumberRangeValue = 2140000000; // bit less than max value of int + + KisMarkerPainter(KisPaintDeviceSP device, const KoColor &color); ~KisMarkerPainter(); @@ -43,6 +47,22 @@ private: struct Private; const QScopedPointer m_d; + + /// This method is to check whether the number is not infinite + /// or negative infinite with some epsilon + /// (@see ValidNumberRangeValue) + /// @param number value entered by the user + /// @return true if number is in range, false otherwise + bool isNumberInValidRange(qint32 number); + + + /// This method is to check whether the rectangle has only valid numbers + /// as values for x, y, height and width. + /// If values are not valid, Sequential Iterator can give incorrect values. + /// (@see isNumberInValidRange, ValidNumberRangeValue) + /// @param number value entered by the user + /// @return true if rect's values is in range, false otherwise + bool isRectInValidRange(const QRect &rect); }; #endif /* __KIS_MARKER_PAINTER_H */ diff --git a/libs/image/kis_marker_painter.cpp b/libs/image/kis_marker_painter.cpp --- a/libs/image/kis_marker_painter.cpp +++ b/libs/image/kis_marker_painter.cpp @@ -44,6 +44,23 @@ { } + + +bool KisMarkerPainter::isNumberInValidRange(qint32 number) +{ + if (number < -ValidNumberRangeValue || number > ValidNumberRangeValue) + return false; + return true; +} + +bool KisMarkerPainter::isRectInValidRange(const QRect &rect) +{ + return isNumberInValidRange(rect.x()) + && isNumberInValidRange(rect.y()) + && isNumberInValidRange(rect.width()) + && isNumberInValidRange(rect.height()); +} + void KisMarkerPainter::fillHalfBrushDiff(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF ¢er, qreal radius) { @@ -63,7 +80,12 @@ boundRect = KisAlgebra2D::cutOffRect(boundRect, plane1); boundRect = KisAlgebra2D::cutOffRect(boundRect, plane2); - KisSequentialIterator it(m_d->device, boundRect.toAlignedRect()); + QRect alignedRect = boundRect.toAlignedRect(); + + KIS_SAFE_ASSERT_RECOVER_RETURN(isRectInValidRange(alignedRect)); + + KisSequentialIterator it(m_d->device, alignedRect); + while (it.nextPixel()) { QPoint pt(it.x(), it.y()); @@ -104,7 +126,11 @@ KisAlgebra2D::OuterCircle outer(center, radius); - KisSequentialIterator it(m_d->device, boundRect.toAlignedRect()); + QRect alignedRect = boundRect.toAlignedRect(); + + KIS_SAFE_ASSERT_RECOVER_RETURN(isRectInValidRange(alignedRect)); + + KisSequentialIterator it(m_d->device, alignedRect); while (it.nextPixel()) { QPoint pt(it.x(), it.y());