fix amount arithmetic

This commit is contained in:
Florian Dold 2016-02-22 23:12:57 +01:00
parent 2760591d4d
commit 268ca99244

View File

@ -105,6 +105,7 @@ export interface ReserveCreationInfo {
mintInfo: IMintInfo; mintInfo: IMintInfo;
selectedDenoms: Denomination[]; selectedDenoms: Denomination[];
withdrawFee: AmountJson; withdrawFee: AmountJson;
overhead: AmountJson;
} }
@ -157,7 +158,7 @@ export namespace Amounts {
saturated: boolean; saturated: boolean;
} }
function getMaxAmount(currency: string) { function getMaxAmount(currency: string): AmountJson {
return { return {
currency, currency,
value: Number.MAX_SAFE_INTEGER, value: Number.MAX_SAFE_INTEGER,
@ -165,25 +166,39 @@ export namespace Amounts {
} }
} }
export function add(first: AmountJson, ...rest: AmountJson[]): Result { export function getZero(currency: string): AmountJson {
let currency = first.currency; return {
let value = first.value + Math.floor(first.fraction / 1e6); currency,
if (value > Number.MAX_SAFE_INTEGER) { value: 0,
return {amount: getMaxAmount(currency), saturated: true}; fraction: 0,
} }
let fraction = first.fraction; }
for (let x of rest) {
if (x.currency !== currency) {
throw Error(`Mismatched currency: ${x.currency} and ${currency}`);
}
fraction = (fraction + x.fraction) % 1e6; export function add(first: AmountJson, ...rest: AmountJson[]): Result {
value = value + x.value + (Math.floor(fraction + x.fraction) / 1e6); const doit = () => {
let currency = first.currency;
let value = first.value + Math.floor(first.fraction / 1e6);
if (value > Number.MAX_SAFE_INTEGER) { if (value > Number.MAX_SAFE_INTEGER) {
return {amount: getMaxAmount(currency), saturated: true}; return {amount: getMaxAmount(currency), saturated: true};
} }
} let fraction = first.fraction % 1e6;
return {amount: {currency, value, fraction}, saturated: false}; for (let x of rest) {
if (x.currency !== currency) {
throw Error(`Mismatched currency: ${x.currency} and ${currency}`);
}
value = value + x.value + Math.floor((fraction + x.fraction) / 1e6);
fraction = (fraction + x.fraction) % 1e6;
if (value > Number.MAX_SAFE_INTEGER) {
return {amount: getMaxAmount(currency), saturated: true};
}
}
return {amount: {currency, value, fraction}, saturated: false};
};
console.log("adding", first, "and", rest);
let ret = doit();
console.log("result is", ret);
return ret;
} }
@ -199,7 +214,7 @@ export namespace Amounts {
return {amount: {currency, value: 0, fraction: 0}, saturated: true}; return {amount: {currency, value: 0, fraction: 0}, saturated: true};
} }
value--; value--;
fraction = +1e6; fraction += 1e6;
} }
console.assert(fraction >= b.fraction); console.assert(fraction >= b.fraction);
fraction -= b.fraction; fraction -= b.fraction;
@ -211,30 +226,51 @@ export namespace Amounts {
} }
export function cmp(a: AmountJson, b: AmountJson): number { export function cmp(a: AmountJson, b: AmountJson): number {
if (a.currency !== b.currency) { const doit = () => {
throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`); if (a.currency !== b.currency) {
} throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);
let av = a.value + Math.floor(a.fraction / 1e6); }
let af = a.fraction % 1e6; let av = a.value + Math.floor(a.fraction / 1e6);
let bv = b.value + Math.floor(b.fraction / 1e6); let af = a.fraction % 1e6;
let bf = b.fraction % 1e6; let bv = b.value + Math.floor(b.fraction / 1e6);
switch (true) { let bf = b.fraction % 1e6;
case av < bv: switch (true) {
return -1; case av < bv:
case av > bv: return -1;
return 1; case av > bv:
case af < bf: return 1;
return -1; case af < bf:
case af > bf: return -1;
return 1; case af > bf:
case af == bf: return 1;
return 0; case af == bf:
default: return 0;
throw Error("assertion failed"); default:
throw Error("assertion failed");
}
};
console.log("comparing", a, "and", b);
let res = doit();
console.log("result:", res);
return res;
}
export function copy(a: AmountJson): AmountJson {
return {
value: a.value,
fraction: a.fraction,
currency: a.currency,
} }
} }
export function isNonZero(a: AmountJson) {
return a.value > 0 || a.fraction > 0;
}
} }
export interface Notifier { export interface Notifier {
notify(); notify();
} }