--- a/lib/Mail/SpamAssassin/BayesStore.pm
+++ b/lib/Mail/SpamAssassin/BayesStore.pm
@@ -346,7 +346,7 @@
     dbg("bayes: can't use estimation method for expiry, unexpected result, calculating optimal atime delta (first pass)");
 
     my $start = $self->{expiry_period}; # exponential search starting at ...?  1/2 day, 1, 2, 4, 8, 16, ...
-    my $max_expire_mult = 2**$self->{expiry_max_exponent}; # $max_expire_mult * $start = max expire time (256 days), power of 2.
+    my $max_expire_mult = $self->{expiry_max_exponent}**2; # $max_expire_mult * $start = max expire time (256 days), power of 2.
 
     dbg("bayes: expiry max exponent: ".$self->{expiry_max_exponent});
 
@@ -358,8 +358,8 @@
     if (would_log('dbg', 'bayes')) {
       dbg("bayes: atime\ttoken reduction");
       dbg("bayes: ========\t===============");
-      for(my $i = 1; $i<=$max_expire_mult; $i <<= 1) {
-	dbg("bayes: ".$start*$i."\t".(exists $delta{$i} ? $delta{$i} : 0));
+      for(my $i = 1, my $m = 1; $m <= $max_expire_mult; $i++, $m = $i**2) {
+	dbg("bayes: ".$start*$m."\t".(exists $delta{$m} ? $delta{$m} : 0));
       }
     }
   
@@ -367,10 +367,10 @@
     # going over ...  Go from the largest delta backwards so the reduction size increases
     # (tokens that expire at 4 also expire at 3, 2, and 1, so 1 will always be the largest expiry...)
     #
-    for( ; $max_expire_mult > 0; $max_expire_mult>>=1 ) {
+    for( my $i = $self->{expiry_max_exponent} ; $i > 0; $i--, $max_expire_mult = $i**2 ) {
       next unless exists $delta{$max_expire_mult};
       if ($delta{$max_expire_mult} > $goal_reduction) {
-        $max_expire_mult<<=1; # the max expire is actually the next power of 2 out
+        $max_expire_mult = ($i+1)**2; # the max expire is actually the square
         last;
       }
     }
--- a/lib/Mail/SpamAssassin/BayesStore/SQL.pm
+++ b/lib/Mail/SpamAssassin/BayesStore/SQL.pm
@@ -257,8 +257,12 @@
     return %delta;
   }
 
-  for (my $i = 1; $i <= $max_expire_mult; $i<<=1) {
-    my $rc = $sth->execute($self->{_userid}, $newest_atime - $start * $i);
+  +  for (my $i = 1; $i**2 <= $max_expire_mult; $i++) {
+	  +
+	  +    my $rc = $sth->execute($self->{_userid}, $newest_atime - $start * $i**2);
+
+  for (my $i = 1, my $m = 1; $m <= $max_expire_mult; $i++, $m = $i**2) {
+    my $rc = $sth->execute($self->{_userid}, $newest_atime - $start * $m);
 
     unless ($rc) {
       dbg("bayes: calculate_expire_delta: SQL error: ".$self->{_dbh}->errstr());
@@ -267,7 +271,7 @@
 
     my ($count) = $sth->fetchrow_array();
 
-    $delta{$i} = $count;
+    $delta{$m} = $count;
   }
   $sth->finish();
 
--- a/lib/Mail/SpamAssassin/BayesStore/BDB.pm
+++ b/lib/Mail/SpamAssassin/BayesStore/BDB.pm
@@ -359,9 +359,9 @@
     # Go through from $start * 1 to $start * 512, mark how many tokens
     # we would expire
     my $age = $newest_atime - $atime;
-    for (my $i = 1; $i <= $max_expire_mult; $i <<= 1) {
-      if ($age >= $start * $i) {
-        $delta{$i}++;
+    for (my $i = 1, my $m = 1; $m <= $max_expire_mult; $i++. $my = $i**2) {
+      if ($age >= $start * $m) {
+        $delta{$m}++;
       } else {
         # If the token age is less than the expire delta, it'll be
         # less for all upcoming checks too, so abort early.
--- a/lib/Mail/SpamAssassin/BayesStore/DBM.pm
+++ b/lib/Mail/SpamAssassin/BayesStore/DBM.pm
@@ -634,9 +634,9 @@
     # Go through from $start * 1 to $start * 512, mark how many tokens
     # we would expire
     my $token_age = $newest_atime - $atime;
-    for (my $i = 1; $i <= $max_expire_mult; $i<<=1) {
-      if ($token_age >= $start * $i) {
-        $delta{$i}++;
+    for (my $i = 1, my $m = 1; $m <= $max_expire_mult; $i++, $m = $i**2) {
+      if ($token_age >= $start * $m) {
+        $delta{$m}++;
       }
       else {
         # If the token age is less than the expire delta, it'll be
