
Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Thanks for the feedback. Your list of identifiers affected by BF mode included $min $max, and since they behave like the various modes of $sorttok I assume that is also counted. Fixed. The sorting routine used by $min() $max() and $sorttok() had not been updated to handle big floats. I have also updated this for /filter when sorting numbers. This is a case where my suggested digits parameter for $calc and $log could help obtain good results without needing to wrap $round() around the output I would prefer not to make changes to existing identifiers in this way. I could technically add a rounding parameter to every numberrelated feature. The $round() identifier is meant to handle this. 2 types of BF mode $powmod() gpf crashes By the gods. This took time to track down. It is, as far as I can tell, a bug in the MAPM library. I reverted the few changes I made to the library to test this and it is happening in the original library. It was due to MAPM returning everincreasing decimal places when calculating "base = base * base % modulus" as it iterated through the while loop. Since the "base" variable is instantianted at the beginning of the loop, the more calculations performed on it, the more decimal places accrued. At a certain point, they started doubling in length with each iteration, resulting in thousands of decimal places. This is happening in the m_apm_multiply() function. This function calls a M_apm_normalize() at the end to strip away trailing zeros but it does not adjust the decimal places to a length that is reasonable for the calculation. I have added code to this function so that it truncates the decimal places in the result to a reasonable size based on the inputs. This resolves the freeze issue. Let's see how this works out in the next beta. So, if this is going to be used in doubles mode, the user needs to be warned that using this in doubles mode can easily return bad results when the modulus exceeds sqrt(2^53), such as (odd,anything,even) returning an impossible even result $powmod(3,46,$calc(2^32)). This is an issue with all calculations prior to bigfloat. It is not specific to $powmod(). Possible partial fix for $calc ^ Fixed. //var s %mersenne_twister.bf $calc(2^19937 1) Fixed. This was happening due to mIRC thinking the result was longer than the maximum string length. In such cases, it returns zero. There are no plans to add support for this just yet. I am focusing on bigfloat. Updated parameter checking on $gcd and $lcm I am allowing a single number and floats for both of these. My unit tests script for bigfloat is getting pretty large now. I have included the tests you've provided in your recent posts. If you have any other tests cases that you think would be useful, let me know and I will add them to the script. Please hold off testing bigfloats in the current beta for now, as the next beta should resolve a number of issues. These changes will be in the next beta.




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
The latest beta includes a number of changes/fixes to bigfloat.
Bigfloat is now passing my 100+ unit tests.
Note that I have not had a chance to update $powmod() with your updated algorithm. This should be in the next beta.
This beta also does not include the /bigfloat d switch yet as I would like to make sure bigfloat is stable first.
Please let me know how this beta works out for you.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
Bigfloat feedback on 4rd beta.  So yes, scripts will need to determine the appropriate length of fraction to wrap $round() around some results, so in this situation they need to use $round to limit the precision to maybe 10 digits or so.
//var s %a.bf $beta $log2(2)
* Set %a.bf to 1743 0.99999999999999999489848895823 * Set %a.bf to 2385 0.999999999999999985890799396948 .  Just confirming that negative exponents still gpf's the powmod, but floats as exponent are $int(parm2)
.  /bigfloat dN
This setting you mentioned in other thread, since there's no backwards compatibility against a beta, instead of adding a $bigfloat().digits property, another option could be that the identifier could change from $true $false, and could be 0=doubles.mode and a number indicating the digits setting. That is, assuming it wouldn't be possible to set it to d0. .  $calc(^) $base() padding
Yay, at first stab I also am not able to find inaccurate integer results, including strings longer than $maxlenl.
However now that there is improved accuracy, it exposes the padding issue I referred to last time, where zeropad has max 100, and I hadn't examined far enough to find that the precision parameter has max 10 digits.
Formerly it didn't matter in doubles mode that zeropad had a max of 100 digits because the accuracy was 53 bits. At first I thought I'd happened to have stumbled across a current error in the $base calculation that wasn't stamped out, but it turned out that a large $powmod result translated to base16 was accurate, but wasn't being zeropad'ed to the length used in Parm4.
Likewise for floats, with $base now able to return 30 digit fractions, using the precision parameter to shorten the 30 digits to any other number cannot result in a fraction longer than 10.
The current workaround for the $base zeropad limit for integers is to use the example string manipulation below. If the string is a float instead of an integer, the string manipulation is only slightly more complex.
For those wanting fractions from $base, it depends on what kind of results they want. From outbase=10 results it appears that the intent of $base is to always return truncated integers rather than rounding them, so if needing outbase=10 fractions rounded, the script should probably avoid using the $base precision parameter, and use $round instead.
//var s %a.bf $sha512(test9)  var %b.bf $base(%a.bf,16,10)  var s %c.bf $base(%b.bf,10,16,$len(%a.bf))  if ($len(%c.bf) < $len(%a.bf)) var s %d.bf $str(0,$calc($v2  $v1)) $+ %c.bf  echo a $len(%a.bf) vs $len(%c.bf) vs $len(%d.bf)
* 128 vs 127 vs 128
//var s %a.bf 1. $+ $str(5,31) , %b.bf $base(%a.bf,10,10) , %c.bf $base(%a.bf,10,10,1,20) , %d.bf $round(%b.bf,29)  echo a $len($gettok(%b.bf,2,46)) vs $len($gettok(%c.bf,2,46)) vs $len($gettok(%d.bf,2,46))
* 30 vs 10 vs 29
//echo a $base(1.999999,10,10,2,1) = 01.9 .  lcm/gcd fractions/singleparm
I don't plan to use single parm or fractions, so I was just defining the 'official' way that gcd and lcm work, where they're the result of 2+ integers, so fractions need not apply. And in .bf mode I can't get the error conditions to return anything other than the correct 0 result except from using a single parameter containing a float.
In doubles mode, I'm not sure exactly what it's doing, because for $gcd(1.5,2.5) it recognizes that they're both integer multiples of 0.5, but for $gcd(1.6,2.4) it doesn't recognize that they're both integer multiples of 0.8
If I had to define rules for how GCD can support fractions, I would probably assume that I should look to see which is the longer fraction, then determine what is the 10^n multiplier that makes both fractions into integers. Then I'd calculate GCD against the modified integer pair, and if the result is 1, then the result should be either 0, or do like for other cases where it would return result=1/multiplier. So for $gcd(1.6,2.4) it would use multiplier=10 to make both numbers be integers, and then get the result of $gcd(16,24)=8, and then return 8/multiplier = 0.8. But for changing gcd(1.98,1.99) where gcd(198,199)=1, the result would either be 0 or 1/multiplier aka 0.01. Though that would return a lot of 0.01's.
As for how lcm is handling float inputs in doubles mode, it looks like it's using the shortcut of $abs(A*B)/$gcd(A,B), and when the GCD result is zero there can be some weirdly huge numbers due to $calc(number / approximately zero) similar to...
//var s %a.bf $tan(270).deg * Set %a.bf to 26971635138473917813752774720289175420.00639833942873200535778279421
So because $gcd(1.6,2.4) is returning zero, $lcm(1.6,2.4) is doing some rounding against (1.6 * 2.4 / closetozero) and ending up with 8646911284551352. And $lcm(1.98,1.99) is probably doing something similar to end up with 17745083251765228.
The wolframalpha link at the top lets you input for other kind of math problems, and their LCM and GCM commands both seem to return results as I previously described, but they refuse to return results for 1 input or if either input is not integer. In the input box at the above link, it lets you paste math like
gcd(15,25) lcm(2,3,4,5,6,7,8,9)
... and they won't return a result for $gcd(1.5) $gcd(1.5,3) $gcd(1.5,4.5) .  $powmod syntax
Likewise, Wolfram has a 'powermod' function that returns results as I described earlier for all combos of positive/negative/zero parameters. They also handle negative exponents the way I described, making 'powermod(A,1,B)' be the same as the $ModInverse(A,B) of the mod_inverse function found in OpenSSL, but I know floats come first.




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Just confirming that negative exponents still gpf's the powmod, but floats as exponent are $int(parm2) I cannot seem to reproduce this here. Can you provide a $powmod() example that reproduces a gpf for you?




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
Sorry should have specified that it was in doubles mode. But it's the original example in the prior post:
//var s %gpf_crash.bx $powmod(4,5,21)




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
updated:
Also $log2 $log $log10 in beta 2385 gpf's from large inputs in .bf mode.
//var s %gpfcrash1.bf $calc(2^10241)  echo a $log2(%gpfcrash.bf) //var s %gpfcrash2.bf $calc(2^10241)  echo a $log(%gpfcrash.bf) //var s %gpfcrash3.bf $calc(2^10241)  echo a $log10(%gpfcrash.bf)




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Thanks I was able to reproduce the $powmod() issue in doubles mode. I also reproduced the issue with $log()/etc. Both have been fixed for the next beta.
Please hold off testing bigfloat further until the next betas as it includes important fixes.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
It's great that it's much harder to find issues.
Looking at the new $modinv I haven't yet run into anything yet involving integer parameters, but in both doubles/bf mode for modinverse(A,B) the 'A' is ignoring the fraction but the 'B' is not, and and that is making it return some unusual numbers, and causes $modinv(A,B.2) to not match $powmod(A,1,B.2) in the examples below. I'm not planning to use floats for parameters, but this behavior in other identifiers allows us scriptors to be lazy by avoiding a call to $int() to sanitize inputs.
//var s %i 0 , %m 7.2  while (%i isnum 0 %m) { echo ag %i : $powmod(%i,1,%m ) vs $modinv(%i,%m)  inc %I }
0 : 1 vs 1 1 : 1 vs 28 2 : 4 vs 10 3 : 5 vs 4 4 : 2 vs 1 5 : 3 vs 3242591731706750 6 : 6 vs 1 7 : 1 vs 1158068475609551
//var s %i 0 , %m.bf $calc(2^64 11) $+ .1  while (%i isnum 0 10) { echo ag %i : $powmod(%i,1,%m.bf ) vs $modinv(%i,%m.bf)  inc %I }
0 : 1 vs 1 1 : 1 vs 0 2 : 9223372036854775803 vs 83010348331692982223 3 : 6148914691236517202 vs 0 4 : 13835058055282163704 vs 32281802128991715308 5 : 1 vs 14757395258967641284 6 : 3074457345618258601 vs 21521201419327810206 7 : 10540996613548315203 vs 10540996613548315202 8 : 6917529027641081852 vs 6917529027641081851 9 : 14347467612885206804 vs 14347467612885206804 10 : 1 vs 90389045961176802865




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Looking at the new $modinv I haven't yet run into anything yet involving integer parameters, but in both doubles/bf mode for modinverse(A,B) the 'A' is ignoring the fraction but the 'B' is not Thanks this has been fixed for the next version. This was due to an int() not being applied in the loop after each calculation, with different precision/rounding by double/bf modes giving different results.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
The & operator is not supporting .bf mode, and returns odd for all numbers >= 2^32
//bigfloat on  var %num.bf $calc(2^32 4) , %j 10  while (%j) { if (%num.bf & 1) echo a $v1 is odd!  if (%num.bf !& 1) echo a $v1 is even!  inc %num.bf  dec %j }




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
The & operator is not supporting .bf mode, and returns odd for all numbers >= 2^32 Thanks fixed for the next beta. This also affected /set with &.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
This might relate to https://forums.mirc.com/ubbthreads.php/topics/266536/ifoperatorregressionFor how this affects /set &, which in doubles mod is returning a signed 31bit number... Since bigfloat mode has no 2^n against which to be 'signed', does that mean "set %var.bx 4294967295 & 4294967295" would remain as 2147483648 but for %var.bf it would return nonnegative results like $and(N1,N2)




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
Hope this doesn't mean there needs to be a precision slowdown. I first observe this in beta 2385 .bf mode, where for all M >= 2*10^62 $calc(A % M) returns 1 when the result should be M1, for all positive K multipliers.
For this example, C1 incorrectly returns 1, but setting C=2 does return the correct answer. But as M becomes larger, the range of C values returning C instead of MC becomes larger too. For example, with M=2*10^63 it returns the negative result for C as large as 10.
//.bigfloat on  var s %k 1 , %c 1 , %m $calc(2*10^62 +0) , %a $calc(%m * %k  %c)  echo a result: $calc(%a % %m) s/b $calc(%m  %c)




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
From looking at output from the calculator script https://forums.mirc.com/ubbthreads.php/topics/271020/calceditboxcalculatorI noticed that evaluation inside square braces and $eval() belonging to %var.bf is being done in doubles mode if it's the simple 'var/set math' but does get the .bf mode result if the math has 3 terms. Then I realized that this is probably related to the var/set math itself not evaluating in doubles mode in all situations. But it's not caused by the math terms being the $13 parameters. From editbox: /set su9 %var.bf 2 / 3 * Set %var.bf to 0.666667 //set su9 %var.bf 2 / 3 * Set %var.bf to 0.666666666666666666666666666667 //var s %var.bf 2 / 3 * Set %var.bf to 0.666666666666666666666666666667 /calctest 355 / 113 * Set %setmath1.bf to 3.141593 * Set %setmath2.bf to 3.141592920353982300884955752212 * Set %result1.bf to result: 3.141593 * Set %result2.bf to result: 3.141592920353982300884955752212 * Set %result3.bf to result: 3.141593 * Set %result4.bf to result: 3.141592920353982300884955752212 /calctest 355 / 113 + 0 * Set %setmath1.bf to 355 / 113 + 0 * Set %setmath2.bf to 355 / 113 + 0 * Set %result1.bf to result: 3.141592920353982300884955752212 * Set %result2.bf to result: 3.141592920353982300884955752212 * Set %result3.bf to result: 3.141592920353982300884955752212 * Set %result4.bf to result: 3.141592920353982300884955752212 alias calctest {
var %1 $1
set ls %setmath1.bf %1
set ls %setmath2.bf $1
var s %result1.bf result: $calc( [ %1 ] )
var s %result2.bf result: $calc( [ $1 ] )
var s %result3.bf result: $calc( $eval( %1 ,2) )
var s %result4.bf result: $calc( $eval( $1 ,2) )
}




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
I noticed that evaluation inside square braces and $eval() belonging to %var.bf is being done in doubles mode if it's the simple 'var/set math' but does get the .bf mode result if the math has 3 terms. This has always been the case. If you use /set or /var without a calculation, it is assigned as text. As for using different combinations of identifiers, parameters, [] brackets, and so on  I have purposefully not changed the parser in any way to accomodate bigfloat. The only way it can be enabled is by using the /bigfloat command or when the parser, during its normal evaluation process, comes across a %var.bf. The evaluation process/order cannot be changed in any way as that would break all existing scripts.




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Hope this doesn't mean there needs to be a precision slowdown. I first observe this in beta 2385 .bf mode, where for all M >= 2*10^62 $calc(A % M) returns 1 when the result should be M1, for all positive K multipliers. Fixed for the next beta.




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
Since bigfloat mode has no 2^n against which to be 'signed', does that mean "set %var.bx 4294967295 & 4294967295" would remain as 2147483648 but for %var.bf it would return nonnegative results like $and(N1,N2) Yes.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
An aspect of bitwise that I hadn't tested yet, dealing with negative terms, and I'm hoping Talon chips in on this.
It appears that the .bf mode for $xor and $and are not doing it right when exactly 1 of the terms is negative.
In doubles mode, a negative term is cast to positive by adding +2^32 and then the normal XOR or AND operation takes place, so that's making the next pair identical to each other:
//echo a %null.bx same $and($calc(2 + 00*2^32) ,255) = 254 //echo a %null.bx same $and($calc(2 + 01*2^32) ,255) = 254
//echo a %null.bx same $xor($calc(2 + 00*2^32) ,255) = 4294967041 //echo a %null.bx same $xor($calc(2 + 01*2^32) ,255) = 4294967041
However, it appears that in .bf mode that $xor(N1,+N2) is the same as $xor(+N1,+N2), and the same goes for $and.
//echo a %null.bf same $and($calc(2 + 00*2^32) ,255) = 2 //echo a %null.bf same $and($calc(+2 + 00*2^32) ,255) = 2 //echo a %null.bf same $xor($calc(2 + 00*2^32) ,255) = 253 //echo a %null.bf same $xor($calc(+2 + 00*2^32) ,255) = 253
I'm not saying that it's wrong for the .bf mode answer to be different than the doubles mode result when 1 term is negative, but that the result shouldn't be based on $abs(negative number)
* *
I'm thinking the solution for when exactly 1 of the $xor $or $and terms is negative:
(A) Negative needs to have 1 << $numbits(positive term) added to it (B) Optional 3rd parm indicating the 1<<N value to add to the negative term, but which would be ignored except when exactly 1 of the 1st 2 terms is negative (C) Both (A) and (B)
For these examples, I took a pair of 64 bit numbers and xor'ed them together, and this shows that A1 is being cast to A2 as $abs(A1) instead of as (A1 + 1<<N), making c1==c2
//bigfloat on  var s %a1 11479905046016372873 , %a2 0  %a1 , %b 16680346320774688079 , %c1 $xor(%a1,%b) , %c2 $xor(%a2,%b) , %bb + $+ $base(%b,10,2,64)  echo 3 a a1 $base(%a1,10,2,64)  echo 5 a ^b %bb  echo 4 a c1 + $+ $base(%c1,10,2,64)  echo 2 a a2 + $+ $base(%a2,10,2,64)  echo 5 a ^b %bb  echo 4 a c2 + $+ $base(%c2,10,2,64)
a1 1001111101010000110100001101000011110011000001010011000010001001 ^b +1110011101111100011111101001101000111100010001001110110101001111 c1 +0111100000101100101011100100101011001111010000011101110111000110 a2 +1001111101010000110100001101000011110011000001010011000010001001 ^b +1110011101111100011111101001101000111100010001001110110101001111 c2 +0111100000101100101011100100101011001111010000011101110111000110
* *
Same thing is happening for $and() where A1 is cast as $abs(A1), and the fix should be the same as for $xor, whether (A) (B) (C)
//bigfloat on  var s %a1 11479905046016372873 , %a2 0  %a1 , %b 16680346320774688079 , %c1 $and(%a1,%b) , %c2 $and(%a2,%b) , %bb + $+ $base(%b,10,2,64)  echo 3 a a1 $base(%a1,10,2,64)  echo 5 a ^b %bb  echo 4 a c1 + $+ $base(%c1,10,2,64)  echo 2 a a2 + $+ $base(%a2,10,2,64)  echo 5 a ^b %bb  echo 4 a c2 + $+ $base(%c2,10,2,64)
* *
Same thing is happening for $or in .bf mode where $or(N1,+N2) is the same as $or(+N1,+N2), and the solution should be whatever it is for $xor and $and
//bigfloat on  var s %a1 11479905046016372873 , %a2 0  %a1 , %b 16680346320774688079 , %c1 $or(%a1,%b) , %c2 $or(%a2,%b) , %bb + $+ $base(%b,10,2,64)  echo 3 a a1 $base(%a1,10,2,64)  echo 5 a ^b %bb  echo 4 a c1 + $+ $base(%c1,10,2,64)  echo 2 a a2 + $+ $base(%a2,10,2,64)  echo 5 a ^b %bb  echo 4 a c2 + $+ $base(%c2,10,2,64)
* *
It seems that a variant of option (C) above has already been implemented for $not without being documented in /help
From a hasty typo due to renaming $xor to $not, I accidentally discovered that at least back to v6.35 that $not ignored a 2nd parm instead of rejecting as invalid syntax, and still ignores it in doubles mode.
However in .bf mode it appears that $not behaves differently than in doubles mode where $not(N) behaves like $xor(N,2^321), but instead returns different results within the < 2^32 range similar to the (C) solution above except as applied to $not, and also does not ignore the 2nd parm.
In .bf mode, $not uses the bit length of $abs(N1) to determine the notmask, but if N2 is present it uses that instead as an override. So some mention in /help $not about the different results from $not in .bf mode seems appropriate, as well as mention of the N2 parm, because I was really confused at first to find that $not(10) was returning '5' because i happened to be in .bf mode, and then when $not(10,5) returned 21 it seemed really confusing. But now what I see where the result comes from, it makes sense
//.bigfloat off  var %i 0  while (%i isnum 032) { echo a %i : ~ %i vs ~ %i ,6 doubles: $not(%i) $not(%i,5) %.bf bf: $not(%i) $not(%i,5)  inc %i }
* *
Another bitwise having issues with negatives is the undocumented $numbits. This identifier is useful because it benchmarks twice as fast as the prior workaround as $len($base(N,10,2)). Plus, it's not limited to getting the bit length of a $maxlenl length outbase=2 string.
Even though $numbits and $base both benchmark much slower than $log2, the known issues for the precision of $log(2) means that you can't use $round or $ceil accurately for very large N, where the example below shows the number well above 2^4096 returning a log as if it's below it.
//var %t $ticksqpc, %a.bf $calc(2^4096 + 2^4051)  var s %res1 $numbits(%a.bf) , %time1 $ticksqpc  %t , %t $ticksqpc , %res2 $len($base(%a.bf,10,2)) , %time2 $ticksqpc  %t , %t $ticksqpc , %res3 $log2(%a.bf) + 1 , %time3 $ticksqpc  %t
* *
However, when I test using the negative numbers, I'm finding results that don't look correct, so I'm appealing to Talon on this one too.
//echo a $numbits(1) %.bf $numbits(1) result: 32 1
At first I was thinking doubles mode returned 32 for for all negative numbers, but that's not the case. If N is in the range [1,2^31] then yes $numbits always returns 32. But if it's in the range [2^31,(2^321)], it instead has different behavior where, if you strip all the leading 1's from $base($abs(N),10,2), that length is used as the bit length.
However if you're in .bf mode, results for negatives always seem to be $numbits($abs(N))
//bigfloat on  :label  var %i 1 , %bitlen 32  while (%i isnum 1 %bitlen) { var %zeroes %i , %ones $calc(%bitlen  %zeroes 1) , %a  $+ $base($str(1,%ones) $+ $str(0,%zeroes) $+ 1 ,2,10)  echo a numbits: $numbits(%a) base2 $base(%a,10,2) base10 %a $bigfloat  inc %i }  if ($bigfloat) { bigfloat off  goto label }
Well, except if (2^32 N) is a power of 2, in which case it's offby1
//var %i 11111 , %c 0  while (%i) { var %a $calc(2^32 %i ) , %base2 $base(%a,10,2) , %string2 $regsubex(%base2,^(1*),)  if ( $len(%string2) != $numbits( $+ %a)) { inc %c  echo a %a : $v1 vs $v2 %base2 $calc(2^32  %a) }  dec %i }  echo a fail %c
4294967040 : 8 vs 9 11111111111111111111111100000000 256 4294967168 : 7 vs 8 11111111111111111111111110000000 128 4294967232 : 6 vs 7 11111111111111111111111111000000 64 4294967264 : 5 vs 6 11111111111111111111111111100000 32 4294967280 : 4 vs 5 11111111111111111111111111110000 16 4294967288 : 3 vs 4 11111111111111111111111111111000 8 4294967292 : 2 vs 3 11111111111111111111111111111100 4 4294967294 : 1 vs 2 11111111111111111111111111111110 2 4294967295 : 0 vs 1 11111111111111111111111111111111 1
It seems logical that the correct behavior for negative N for doubles mode should mimic the $numbits($abs(N)) from .bf mode, and I guess it's consistent behavior with the other bitwise operators for doubles mode to return $numbits(N) = 1 and $numbits(N) = 32 when $abs(N) >= 2^32




Joined: Dec 2002
Posts: 5,230
Hoopy frood

Hoopy frood
Joined: Dec 2002
Posts: 5,230 
I'm not saying that it's wrong for the .bf mode answer to be different than the doubles mode result when 1 term is negative, but that the result shouldn't be based on $abs(negative number) The bitwise bigfloat mode is most definitely different from nonbigfloat mode, eg. nonbigfloat is fixed at 32bit unsigned longs, whereas bigfloat is not fixed. I am pretty sure this was discussed. It also only handles positive values. If you use a negative value, it is $abs()'d. This is intentional. The nonbigfloat mode has always converted doubles to 32bit unsigned longs before applying standard bitwise operators, which can lead to overflows, etc. However, when I test using the negative numbers, I'm finding results that don't look correct, so I'm appealing to Talon on this one too. //echo a $numbits(1) %.bf $numbits(1) result: 32 1 That looks fine and is how I wanted it to work. In the first case, 1 as an unsigned long is 32bits. In the second case, big float with no 'n' specified for the number of bits is one bit since it is $abs(1). There are no plans to change how the bitwise operators in bigfloat mode work. If someone decides to add bitwise operators to the MAPM library natively, I may look into the above again, although by then the behaviour will be established so it may not make any sense to change it.




Joined: Jan 2004
Posts: 1,949
Hoopy frood

Hoopy frood
Joined: Jan 2004
Posts: 1,949 
Hrm, I don't remember discussing that bitwise should use $abs for $xor $and $or. There's a big difference between using 2 (make something be an even number) vs +2 (make something be 2 or 0), and I can't see any scripts finding the $not($abs(N1)) behavior useful.
//echo a $and(255,2) vs %null.bf $and(255,2) $and(255,+2)
Rather than return an obviously wrong answer, I'm wondering if it's better to either require the 3rd 'bits' parameter be present when 1 term is negative for $and $or $xor (and when both terms are negative for $and $or), or to treat $xor(N1,+N2) as invalid syntax in .bf mode.
Likewise, I'm not so sure that $not should have an implied bitmask that's based on the bit length of $abs(N), since that assumes N always has the appropriate bit length.
//echo a doubles $not(9) $not(17) vs $not(9,8) $not(17,8) bf %null.bf $not(9) $not(17) vs $not(9,8) $not(17,8)
In fact, the parm2 used by .bf mode looks like a useful feature for doubles mode instead of defaulting as $not(number,32)




