diff --git a/pyRCV2/method/STVCCounter.py b/pyRCV2/method/STVCCounter.py
index 6ebf713..8d3f167 100644
--- a/pyRCV2/method/STVCCounter.py
+++ b/pyRCV2/method/STVCCounter.py
@@ -29,6 +29,9 @@ class STVCCounter:
def reset(self):
self.candidates = SafeDict([(c, CountCard()) for c in self.election.candidates])
self.exhausted = CountCard()
+ self.loss_fraction = CountCard()
+
+ self.total_orig = sum((b.value for b in self.election.ballots), Num('0'))
# Withdraw candidates
for candidate in self.election.withdrawn:
@@ -57,7 +60,8 @@ class STVCCounter:
'First preferences',
self.candidates,
self.exhausted,
- self.total + self.exhausted.votes,
+ self.loss_fraction,
+ self.total + self.exhausted.votes + self.loss_fraction.votes,
self.quota
)
__pragma__('noopov')
@@ -67,6 +71,7 @@ class STVCCounter:
for candidate, count_card in self.candidates.items():
count_card.step()
self.exhausted.step()
+ self.loss_fraction.step()
# Have sufficient candidates been elected?
if sum(1 for c, cc in self.candidates.items() if cc.state == CandidateState.PROVISIONALLY_ELECTED or cc.state == CandidateState.ELECTED) >= self.election.seats:
@@ -84,7 +89,8 @@ class STVCCounter:
'Bulk election',
self.candidates,
self.exhausted,
- self.total + self.exhausted.votes,
+ self.loss_fraction,
+ self.total + self.exhausted.votes + self.loss_fraction.votes,
self.quota
)
__pragma__('noopov')
@@ -132,7 +138,8 @@ class STVCCounter:
'Surplus of ' + candidate_surplus.name,
self.candidates,
self.exhausted,
- self.total + self.exhausted.votes,
+ self.loss_fraction,
+ self.total + self.exhausted.votes + self.loss_fraction.votes,
self.quota
)
__pragma__('noopov')
@@ -171,7 +178,8 @@ class STVCCounter:
'Exclusion of ' + candidate_excluded.name,
self.candidates,
self.exhausted,
- self.total + self.exhausted.votes,
+ self.loss_fraction,
+ self.total + self.exhausted.votes + self.loss_fraction.votes,
self.quota
)
__pragma__('noopov')
@@ -180,6 +188,7 @@ class STVCCounter:
# Compute quota
__pragma__('opov')
self.total = sum((cc.votes for c, cc in self.candidates.items()), Num('0'))
+ self.loss_fraction.transfers += (self.total_orig - self.total - self.exhausted.votes) - self.loss_fraction.votes
self.quota = self.total / Num(self.election.seats + 1)
__pragma__('noopov')
diff --git a/pyRCV2/model.py b/pyRCV2/model.py
index b8776f4..4fbb22d 100644
--- a/pyRCV2/model.py
+++ b/pyRCV2/model.py
@@ -77,11 +77,12 @@ class CountCompleted:
pass
class CountStepResult:
- def __init__(self, comment, candidates, exhausted, total, quota):
+ def __init__(self, comment, candidates, exhausted, loss_fraction, total, quota):
self.comment = comment
self.candidates = candidates # SafeDict: Candidate -> CountCard
self.exhausted = exhausted # CountCard
+ self.loss_fraction = loss_fraction # CountCard
self.total = total
self.quota = quota
diff --git a/pyRCV2/numbers/__init__.py b/pyRCV2/numbers/__init__.py
index e9a8daf..df655b4 100644
--- a/pyRCV2/numbers/__init__.py
+++ b/pyRCV2/numbers/__init__.py
@@ -23,11 +23,13 @@ __pragma__('noskip')
if is_py:
__pragma__('skip')
from pyRCV2.numbers.fixed_py import Fixed, set_dps
+ from pyRCV2.numbers.int_py import NativeInt
from pyRCV2.numbers.native_py import Native
from pyRCV2.numbers.rational_py import Rational
__pragma__('noskip')
else:
from pyRCV2.numbers.fixed_js import Fixed, set_dps
+ from pyRCV2.numbers.int_js import NativeInt
from pyRCV2.numbers.native_js import Native
from pyRCV2.numbers.rational_js import Rational
diff --git a/pyRCV2/numbers/fixed_py.py b/pyRCV2/numbers/fixed_py.py
index 52530de..1b2f5fd 100644
--- a/pyRCV2/numbers/fixed_py.py
+++ b/pyRCV2/numbers/fixed_py.py
@@ -35,13 +35,13 @@ class Fixed:
return format(self.impl, '.{}f'.format(dp))
def __add__(self, other):
- return Fixed((self.impl + other.impl).quantize(_quantize_exp))
+ return Fixed(self.impl + other.impl)
def __sub__(self, other):
- return Fixed((self.impl - other.impl).quantize(_quantize_exp))
+ return Fixed(self.impl - other.impl)
def __mul__(self, other):
- return Fixed((self.impl * other.impl).quantize(_quantize_exp))
+ return Fixed(self.impl * other.impl)
def __div__(self, other):
- return Fixed((self.impl / other.impl).quantize(_quantize_exp))
+ return Fixed(self.impl / other.impl)
def __gt__(self, other):
return self.impl > other.impl
diff --git a/pyRCV2/numbers/int_js.py b/pyRCV2/numbers/int_js.py
new file mode 100644
index 0000000..6769278
--- /dev/null
+++ b/pyRCV2/numbers/int_js.py
@@ -0,0 +1,45 @@
+# pyRCV2: Preferential vote counting
+# Copyright © 2020 Lee Yingtong Li (RunasSudo)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see