View Full Version : How to convert any integer to mod2
TCmullet
22nd September 2019, 07:38
I compute an integer in a script and integer can be any value. But I need to modify it so that it is mod2 (evenly divisible by 2). How can we do that? (I've hunted but not found anything.) Will I have to write a custom function just to do that? (And I'm not sure yet whether I want to round up or down, or round closer to zero or farther--one step at a time, ha ha.)
Edit: IF we have to have a function, would this do it?
function MakeMod2(int myInt)
{
bitRshift(myInt,1)
bitLshift(myInt,1)
return myInt
}
hello_hello
22nd September 2019, 09:31
Is something like this what you need?
http://avisynth.nl/index.php/Internal_functions#Floor
function MakeMod2(int myInt, int "Rounding") {
# round to nearest integer = 1
# round down = 2
# round up = 3
# round towards zero = any integer other than 1, 2 or 3
rounding = default(rounding, 1)
myFloat = float(myInt)
Mod2Out = \
(rounding == 1) ? round(myFloat / 2.0) * 2 : \
(rounding == 2) ? floor(myFloat / 2.0) * 2 : \
(rounding == 3) ? ceil(myFloat / 2.0) * 2 : \
int(myFloat / 2.0) * 2
return Mod2Out }
For mod4 it'd be
round(myFloat / 4.0) * 4
etc.
Or something similar.
http://avisynth.nl/index.php/Operators
I think Mod (%) works much the same way as FMod, but FMod needs float values.
http://avisynth.nl/index.php/Internal_functions#Fmod
function MakeMod2(int myInt, bool "RoundUp") {
RoundUp = default(RoundUp, false)
Mod2Out = \
(myInt % 2 == 0) ? myInt : \
!RoundUp ? myInt - 1 : \
myInt + 1
return Mod2Out }
StainlessS
22nd September 2019, 10:01
HH, 'myInt' is not defined as an optional arg to your function, but you use 'Default(myInt, 2)'.
Here differing rounding stuff:- https://forum.doom9.org/showthread.php?p=1814184#post1814184
Round value down to next lower multiple of factor ALWAYS
(value-1)/factor*factor
To round up, to the next higher multiple of factor, when value is not an exact multiple of factor.
(value+factor-1)/factor*factor.
To round up, to the next higher multiple of factor, ALWAYS.
(value+factor)/factor*factor
To round to nearest multiple of factor.
(value+factor/2)/factor*factor, OR better yet, (value*2+factor)/(2*factor)*factor. (marginally less prone to intermediate result precision loss)
Where above value and factor are both type int. [above method 2 and 4 most often used, 1 and 3 rarely]
I seem to have missed out round down, [think it was already discussed, and so I missed it out]
value/factor*factor.
EDIT:
Function RoundInt(int value, int "factor", int "roundMode") { # https://forum.doom9.org/showthread.php?p=1885480#post1885480
# Round +ve Int Value to a multiple of +ve Int Factor, using rounding mode RoundMode. Result will not go -ve.
factor = Default(factor,2) # Default round to multiple of 2, even
roundMode=Default(roundMode,0) # 0=Down(Default), 1=Nearest, 2=Up, 3=ALWAYS_DOWN, 4=ALWAYS_UP
Assert(0 <= value,String(value,"RoundInt: 0 <= value(%.0f) [result undefined for -ve value]"))
Assert(0 < factor,String(factor,"RoundInt: 0 < factor(%.0f)"))
Assert(0 <= RoundMode <= 4,String(RoundMode,"RoundInt: 0 <= RoundMode(%.0f) <= 4 "))
return
\ (RoundMode==0) ? value / factor * factor [* Down *]
\ : (RoundMode==1) ? (value*2+factor)/(2*factor)*factor [* Nearest : About same as (value+factor/2)/factor*factor but without intermediate result precision loss *]
\ : (RoundMode==2) ? (value+factor-1)/factor*factor [* Up *]
\ : (RoundMode==3) ? (value-1)/factor*factor [* ALWAYS_DOWN : Rare Use : Result always less than Value, except where Value=0 *]
\ : (value+factor)/factor*factor [* ALWAYS_UP : Rare Use : Result always greater than Value *]
}
FACTOR = 4 # round to multiples of 4
SSS= "Val Down Near Up ADwn AUp\n"
For(i=0,16) {
S=""
for(roundMode=0,4) {
r = RoundInt(i, FACTOR, roundMode)
S = S + String(r,"%5.0f")
}
SSS = SSS + String(i,"%2.0f]") + S + "\n"
}
BlankClip(Width=320,height=360)
Subtitle(SSS,Font="Courier New",lsp=0) # Courier New = MonoSpaced font
https://i.postimg.cc/65p7C1Jt/z-01.jpg (https://postimages.org/)
EDIT:
\ : (RoundMode==1) ? (value*2+factor)/(2*factor)*factor [* Nearest : About same as (value+factor/2)/factor*factor but without intermediate result precision loss *]
where above factor/2 is eg 3/2, then we lose precision due to half of 3 being 1, instead of 1.5 [which we cannot have in type int], chosen method avoids that precision loss at that stage.
Where factor is KNOWN even [EDIT: KNOWN power of 2, including 1] (most cases) then could use the simpler method.
EDIT: Result will not go -ve for any round operation. Value Must be +ve, Factor must be 1 or greater.
hello_hello
22nd September 2019, 15:01
HH, 'myInt' is not defined as an optional arg to your function, but you use 'Default(myInt, 2)'.
Where? :)
Actually I did the same for both functions initially, but for some reason I only removed it from the second one after thinking about it. I've done the same for the first one now.
Cheers.
StainlessS
22nd September 2019, 15:07
You originally had
myInt = Default(myInt, 2)
I can only presume that you removed it in your previous edit after 10:01 BST [I think I copy/pasted "Default(myInt, 2)" from your post].
EDIT: Changed "between 10:01 and about 10:25 BST" to "after 10:01 BST".
hello_hello
22nd September 2019, 16:11
You originally had
Sorry, I thought the smiley would give away the fact I was joking (or being a smart-arse after editing the post). :)
StainlessS
22nd September 2019, 16:25
Sorry, bit under the weather today, significance of smiley not recognised :)
johnmeyer
22nd September 2019, 16:53
I must be missing something because this seems too easy. Don't you just:
1. Divide integer by two
2. Truncate (remove decimal)
3. Multiply by two.
Example 1 (odd numbers)
13
13/2 = 6.5
Truncate = 6.0
Multiply by 2 = 12.0000
Example 1 (even numbers)
14
14/2 = 7.0
Truncate = 7.0
Multiply by 2 = 14.0000
Add one in second step if you want to round up.
manolito
22nd September 2019, 17:18
I use this:
int = 13
mod2 = int - (int % 2) # Round Down
# mod2 = int + (int % 2) # Round up
Too simple to even make a function out of it...
StainlessS
22nd September 2019, 17:29
Thread title:- "How to convert any integer to mod2"
So, forget about floats, not needed.
Example 1 (odd numbers)
13
13/2 = 6.5
Truncate = 6.0
Multiply by 2 = 12.0000
13
13/2 = 6 # int/int = int (truncated int, fractional part discarded)
Multiply by int 2 = 12
so 13/2*2=12
Example 1 (even numbers)
14
14/2 = 7.0
Truncate = 7.0
Multiply by 14.0 # Presume "Multiply by 2 = 14.0"
14/2*2 = 14
Add one in second step if you want to round up.
(value+factor-1)/factor*factor # General round up where factor is variable
where factor=2 (modulo 2)
Round UP (13+2-1)/2*2=14 OR (13+1)/2*2=14
Round UP (14+2-1)/2*2=14 OR (14+1)/2*2=14
EDIT: NOTE, Prev post Manolito Method for Round UP only works for Modulo 2.
integer = integer - (integer % factor) # Manolito method Round Down works OK
integer = integer + (factor - integer % factor) # Modified Manolito Round Up [EDIT: This is a BUM STEER, it dont work ]
Above bugged
manolito
22nd September 2019, 18:50
integer = integer + (factor - integer % factor) # Modified Manolito Round Up
For factors other than two I use this for Round Up:
integer = (integer + factor -1) / factor * factor
But the StainlessS version is simpler which is better...
MeteorRain
22nd September 2019, 19:38
BitAnd(myInt, -2) maybe?
and
BitAnd(myInt + 1, -2) for rounding up.
StainlessS
22nd September 2019, 21:14
MeteorRain,
Note, BitAnd() is a function, with significant lookup overhead (although not so much in avs+ compared to avs std, I think hash table was implemented in avs+),
whereas ops below are done directly via the parser, and quite a bit faster [will though make little difference unless in some runtime script].
\ (RoundMode==0) ? value / factor * factor [* Down *]
\ : (RoundMode==1) ? (value*2+factor)/(2*factor)*factor [* Nearest : About same as (value+factor/2)/factor*factor but without intermediate result precision loss *]
\ : (RoundMode==2) ? (value+factor-1)/factor*factor [* Up *]
\ : (RoundMode==3) ? (value-1)/factor*factor [* ALWAYS_DOWN : Rare Use <EDIT: Result always less than Value, except where Value=0> *]
\ : (value+factor)/factor*factor [* ALWAYS_UP : Rare Use <EDIT: Result always greater than Value> *]
EDIT: Also, I suggest that method that works for all values of factor is a better option, with possible exception being above Simpler Nearest when factor is power of 2(1,2,4 etc, likely most often).
MeteorRain
23rd September 2019, 07:36
Thanks, lesson learned.
StainlessS
23rd September 2019, 15:25
But the StainlessS version is simpler which is better...
Maybe simpler, but NOT better, sorry, was a bum steer, ie it dont work.
FACTOR=4
SSS= ""
For(integer=0,16) {
r = integer + (factor - integer % factor)
S = String(r,"%5.0f")
SSS = SSS + String(integer,"%2.0f]") + S + "\n"
}
BlankClip(Width=320,height=360)
Subtitle(SSS,Font="Courier New",lsp=0) # Courier New = MonoSpaced font
https://i.postimg.cc/qBj9mwDp/bumsteer.jpg (https://postimages.org/)
Guess I shoulda checked it first before posting.
Is same as RoundInt(roundMode = 4), ALWAYS_UP. (should be same as below UP column.
https://i.postimg.cc/65p7C1Jt/z-01.jpg (https://postimages.org/)
EDIT:
Thanks, lesson learned.
Yip, tis a lesson that many coders will need learn at some stage (me included), it is 2nd nature to presume that bit operations are fast.
manolito
23rd September 2019, 15:37
Nice...
My version came directly from Gavino, so I knew that it is correct. :D
StainlessS
23rd September 2019, 15:52
For factors other than two I use this for Round Up:
integer = (integer + factor -1) / factor * factor
If your are talking about the above, then it is the 'standard' way to do it, and same as post #3 RoundInt(roundMode=2).
EDIT:
When factor is KNOWN 2, then, is
(integer + 2 - 1) / 2 * 2 <===> (integer + 1) / 2 * 2
(integer + 0) / 1 * 1 # Known 1, ie same as integer=integer
(integer + 1) / 2 * 2 # Known 2
(integer + 2) / 3 * 3 # Known 3
(integer + 3) / 4 * 4 # Known 4, etc
Gavino
23rd September 2019, 19:17
My version came directly from Gavino, so I knew that it is correct. :D
Thanks, Manolito!
I don't have much time for posting these days, but it's nice to see my memory lives on ... :D
manolito
24th September 2019, 00:30
I don't have much time for posting these days, but it's nice to see my memory lives on ... :D
Being forgotten by the AVS community should be one of your least concerns, this will not happen...
You helped me solving the above issue in 2012
https://forum.doom9.org/showthread.php?p=1574277#post1574277
And there were many other occasions when I hit a roadblock in an AVS script that your posts in different threads saved me. So I am the one who has to thank you... :thanks:
johnmeyer
24th September 2019, 01:33
Thanks, Manolito!
I don't have much time for posting these days, but it's nice to see my memory lives on ... :DI think of you every time I type "Global" in one of my scripts and think, oh no, he would NOT approve of this.
StainlessS
24th September 2019, 09:50
That Gavino h'm, off galavanting around the temples of Nepal, you mark my words, he'll be back just as soon as he's found himself. [Oh, to be young and daft again]
rgr
12th March 2025, 22:37
I compute an integer in a script and integer can be any value. But I need to modify it so that it is mod2 (evenly divisible by 2)
a=round(value/2)*2
Late, but this thread needs an answer :)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.