|
Joined: Dec 2002
Posts: 5,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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 number-related 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 ever-increasing 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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
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/single-parm
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 / close-to-zero) 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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
updated:
Also $log2 $log $log10 in beta 2385 gpf's from large inputs in .bf mode.
//var -s %gpfcrash1.bf $calc(2^1024-1) | echo -a $log2(%gpfcrash.bf) //var -s %gpfcrash2.bf $calc(2^1024-1) | echo -a $log(%gpfcrash.bf) //var -s %gpfcrash3.bf $calc(2^1024-1) | echo -a $log10(%gpfcrash.bf)
|
|
|
|
Joined: Dec 2002
Posts: 5,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
This might relate to https://forums.mirc.com/ubbthreads.php/topics/266536/if-operator-regressionFor how this affects /set &, which in doubles mod is returning a signed 31-bit 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 non-negative results like $and(N1,N2)
|
|
|
|
Joined: Jan 2004
Posts: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
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 M-1, for all positive K multipliers.
For this example, C-1 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 M-C 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: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
From looking at output from the calculator script https://forums.mirc.com/ubbthreads.php/topics/271020/calc-editbox-calculatorI 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 $1-3 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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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 M-1, for all positive K multipliers. Fixed for the next beta.
|
|
|
|
Joined: Dec 2002
Posts: 5,482
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,482 |
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 non-negative results like $and(N1,N2) Yes.
|
|
|
|
Joined: Dec 2002
Posts: 343
Pan-dimensional mouse
|
OP
Pan-dimensional mouse
Joined: Dec 2002
Posts: 343 |
https://www.mirc.com/versions.txt10.Extended $base() to handle big numbers. Thank you.
|
|
|
|
|