perl6: why is array skipping calculated values inside declaration?

  • A+
Category:Languages

I am learning Perl6 from Perl5.

In order to make this compile, I'll post the whole program:

sub lgamma ( Num(Real) /n --> Num ){   use NativeCall;   sub lgamma (num64 --> num64) is native {}   lgamma( n ) }  sub pvalue (@a, @b) {   if @a.elems <= 1 {     return 1.0;   }   if @b.elems <= 1 {     return 1.0;   }   my Rat $mean1 = @a.sum / @a.elems;   my Rat $mean2 = @b.sum / @b.elems;   if $mean1 == $mean2 {     return 1.0;   }   my Rat $variance1 = 0.0;   my Rat $variance2 = 0.0;    for @a -> $i {     $variance1 += ($mean1 - $i)**2#";" unnecessary for last statement in block   }   for @b -> $i {     $variance2 += ($mean2 - $i)**2   }   if ($variance1 == 0 && $variance2 == 0) {     return 1.0;   }   $variance1 /= (@a.elems - 1);   $variance2 /= (@b.elems - 1);    my $WELCH_T_STATISTIC = ($mean1-$mean2)/sqrt($variance1/@a.elems+$variance2/@b.elems);     my $DEGREES_OF_FREEDOM = (($variance1/@a.elems+$variance2/@b.elems)**2)     /     (     ($variance1*$variance1)/(@a.elems*@a.elems*(@a.elems-1))+     ($variance2*$variance2)/(@b.elems*@b.elems*(@b.elems-1))     );     my $A = $DEGREES_OF_FREEDOM/2;     my $value = $DEGREES_OF_FREEDOM/($WELCH_T_STATISTIC*$WELCH_T_STATISTIC+$DEGREES_OF_FREEDOM);   my Num $beta = lgamma($A)+0.57236494292470009-lgamma($A+0.5);     my Rat $acu = 10**(-15);     my ($ai,$cx,$indx,$ns,$pp,$psq,$qq,$rx,$temp,$term,$xx); # Check the input arguments.     return $value if $A <= 0.0;# || $q <= 0.0;     return $value if $value < 0.0 || 1.0 < $value; # Special cases     return $value if $value == 0.0 || $value == 1.0;     $psq = $A + 0.5;     $cx = 1.0 - $value;     if $A < $psq * $value {         ($xx, $cx, $pp, $qq, $indx) = ($cx, $value, 0.5, $A, 1);     } else {         ($xx, $pp, $qq, $indx) = ($value, $A, 0.5, 0);     }     $term = 1.0;     $ai = 1.0;     $value = 1.0;     $ns = $qq + $cx * $psq;   $ns = $ns.Int; #Soper reduction formula.     $rx = $xx / $cx;     $temp = $qq - $ai;     $rx = $xx if $ns == 0;     while (True) {         $term = $term * $temp * $rx / ( $pp + $ai );         $value = $value + $term;         $temp = $term.abs;         if $temp <= $acu && $temp <= $acu * $value {         $value = $value * ($pp * $xx.log + ($qq - 1.0) * $cx.log - $beta).exp / $pp;         $value = 1.0 - $value if $indx;         last;         }         $ai++;         $ns--;         if 0 <= $ns {             $temp = $qq - $ai;             $rx = $xx if $ns == 0;         } else {             $temp = $psq;             $psq = $psq + 1.0;         }     }     return $value; }  my @array2d = ([27.5,21.0,19.0,23.6,17.0,17.9,16.9,20.1,21.9,22.6,23.1,19.6,19.0,21.7,21.4],  [27.1,22.0,20.8,23.4,23.4,23.5,25.8,22.0,24.8,20.2,21.9,22.1,22.9,20.5,24.4],#0.   [17.2,20.9,22.6,18.1,21.7,21.4,23.5,24.2,14.7,21.8],  [21.5,22.8,21.0,23.0,21.6,23.6,22.5,20.7,23.4,21.8,20.7,21.7,21.5,22.5,23.6,21.5,22.5,23.5,21.5,21.8],   [19.8,20.4,19.6,17.8,18.5,18.9,18.3,18.9,19.5,22.0],  [28.2,26.6,20.1,23.3,25.2,22.1,17.7,27.6,20.6,13.7,23.2,17.5,20.6,18.0,23.9,21.6,24.3,20.4,24.0,13.2],   [30.02,29.99,30.11,29.97,30.01,29.99],  [29.89,29.93,29.72,29.98,30.02,29.98],   [3.0,4.0,1.0,2.1],  [490.2,340.0,433.9],   [<1.0/15.0>, <10.0/62.0>],  [<1.0/10>, <2/50.0>],   [0.010268,0.000167,0.000167],  [0.159258,0.136278,0.122389],   [9/23.0,21/45.0,0/38.0],  [0/44.0,42/94.0,0/22.0]);   say @array2d[11][0];   my @CORRECT_ANSWERS = (0.021378001462867,  0.148841696605327,  0.0359722710297968,  0.090773324285671,  0.0107515611497845,  0.00339907162713746,  0.52726574965384,  0.545266866977794);  my UInt $i = 0; my Real $error = 0.0; for @array2d -> @left, @right {   my $pvalue = pvalue(@left, @right);   $error += ($pvalue - @CORRECT_ANSWERS[$i]).abs;   say "$i [" ~ @left.join(',') ~ '] [' ~ @right ~ "] = $pvalue";   if $error > 10**-9 {     say "/$p = $pvalue, but should be @CORRECT_ANSWERS[$i]";     die;   } #  printf("Test sets %u p-value = %.14g/n",$i+1,$pvalue);   $i++ }  printf("the cumulative error is %g/n", $error); 

What makes this sub-array different is that it has the "/" for division. How can I make Perl6 for-loop evaluate this sub-array?

EDIT: I'm struggling with what constitutes a minimal working example. I'm posting the entire code so that it will compile.

 


Third and final answer

.oO (He says, hopefully. Has anyone ever written four answers to an SO question?!? 🤭 )

If you swap these lines in your data:

  [<1.0/15.0>, <10.0/62.0>],   [<1.0/10>, <2/50.0>],    [0.010268,0.000167,0.000167],   [0.159258,0.136278,0.122389], 

to instead be the other way around:

  [0.010268,0.000167,0.000167],   [0.159258,0.136278,0.122389],    [<1.0/15.0>, <10.0/62.0>],   [<1.0/10>, <2/50.0>], 

then the output of your program (at least my version of it from my rewrite of your code nanswer) is:

0.159258 0 [27.5,21,19,23.6,17,17.9,16.9,20.1,21.9,22.6,23.1,19.6,19,21.7,21.4] [27.1 22 20.8 23.4 23.4 23.5 25.8 22 24.8 20.2 21.9 22.1 22.9 20.5 24.4] = 0.02137800146286709 1 [17.2,20.9,22.6,18.1,21.7,21.4,23.5,24.2,14.7,21.8] [21.5 22.8 21 23 21.6 23.6 22.5 20.7 23.4 21.8 20.7 21.7 21.5 22.5 23.6 21.5 22.5 23.5 21.5 21.8] = 0.14884169660532756 2 [19.8,20.4,19.6,17.8,18.5,18.9,18.3,18.9,19.5,22] [28.2 26.6 20.1 23.3 25.2 22.1 17.7 27.6 20.6 13.7 23.2 17.5 20.6 18 23.9 21.6 24.3 20.4 24 13.2] = 0.035972271029797116 3 [30.02,29.99,30.11,29.97,30.01,29.99] [29.89 29.93 29.72 29.98 30.02 29.98] = 0.09077332428566681 4 [3,4,1,2.1] [490.2 340 433.9] = 0.010751561149784494 5 [0.010268,0.000167,0.000167] [0.159258 0.136278 0.122389] = 0.003399071627137453 6 [1.0/15.0,10.0/62.0] [1.0/10 2/50.0] = 0.5272657496538401 7 [0.391304,0.466667,0] [0 0.446809 0] = 0.5452668669777938 the cumulative error is 5.50254e-15 

In retrospect this was very obviously what was wrong. 2020 hindsight and all that. :)

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: