use paste::paste;
mod multiply_scaled_u64_slices_with_prec_into {
use super::*;
macro_rules! impl_case {
($name:ident: $prec:literal => [$($le_d:literal),*] E $exp:literal) => {
impl_case!($name: round=Up; $prec => [$($le_d),*] E $exp);
};
($name:ident: round=$round:ident; $prec:literal => [$($le_d:literal),*] E $exp:literal) => {
impl_case!($name: round=$round; $prec => Plus [$($le_d),*] E $exp);
};
($name:ident: round=$round:ident; $prec:literal => $sign:ident [$($expected:literal),*] E $exp:literal) => {
#[test]
fn $name() {
let a = input_a();
let b = input_b();
let prec = NonZeroU64::new($prec).unwrap();
let expected: &[u64] = &[$($expected),*];
let expected_scale = -$exp;
let rounding = NonDigitRoundingData {
mode: RoundingMode::$round,
sign: Sign::$sign,
};
let mut product = WithScale::default();
multiply_scaled_u64_slices_with_prec_into(
&mut product, a.as_digit_slice(), b.as_digit_slice(), prec, rounding
);
assert_eq!(&product.value.digits[..], &expected[..]);
assert_eq!(product.scale, expected_scale);
}
};
}
mod case_1667660160137446952e158 {
use super::*;
fn input_a() -> WithScale<DigitVec<RADIX_u64, LittleEndian>> {
WithScale {
scale: 34,
value: DigitVec::from_vec(vec![
16175263208544711346,
5279606946643537445,
15341572592040251541,
10541804148642044343,
7522665456306621740,
13427633752471237939,
16469249152156353442,
11787750781150891403,
3583949032441389106,
18383297448742447850,
365519312995810676,
]),
}
}
mod times_2d998213en173 {
use super::*;
fn input_b() -> WithScale<DigitVec<RADIX_u64, LittleEndian>> {
WithScale {
scale: 272,
value: DigitVec::from_vec(vec![
1344009339610453499,
6464650240578252661,
13739370975302393952,
1107949409989368443,
12288971738008765224,
1403
]),
}
}
impl_case!(prec19_roundup: round=Up;
19 => [5000000000000000001] E -15);
impl_case!(prec20_roundup: round=Up;
20 => [13106511852580896769, 2] E -16);
impl_case!(prec100_roundup: round=Up;
100 => [1, 6059390473091416064, 5120748075179647364, 14006871066438625056, 15461642991872345491, 2340] E -96);
impl_case!(neg_prec100_roundceiling: round=Ceiling;
100 => Minus [0, 6059390473091416064, 5120748075179647364, 14006871066438625056, 15461642991872345491, 2340] E -96);
impl_case!(neg_prec100_roundfloor: round=Floor;
100 => Minus [1, 6059390473091416064, 5120748075179647364, 14006871066438625056, 15461642991872345491, 2340] E -96);
}
mod times_5996425554en186 {
use super::*;
fn input_b() -> WithScale<DigitVec<RADIX_u64, LittleEndian>> {
WithScale {
scale: 204,
value: DigitVec::from_vec(
vec![12019064456476625820, 325066880]
),
}
}
impl_case!(prec1_roundup: round=Up; 1 => [1] E 0);
impl_case!(prec1_rounddown: round=Down; 1 => [9] E -1);
impl_case!(prec1_roundfloor: round=Floor; 1 => [9] E -1);
impl_case!(neg_prec1_rounddown: round=Down; 1 => Minus [9] E -1);
impl_case!(neg_prec1_roundfloor: round=Floor; 1 => Minus [1] E 0);
impl_case!(prec10_roundup: round=Floor; 10 => Minus [1000000000] E -9);
impl_case!(prec25_roundup: round=Floor; 25 => Minus [2003764205206896640, 54210] E -24);
impl_case!(prec40_roundup: round=Up;
40 => [13399721896776114178, 7145508105175220139, 29] E -40);
}
mod times_7303919561276644672e10 {
use super::*;
fn input_b() -> WithScale<DigitVec<RADIX_u64, LittleEndian>> {
WithScale {
scale: 7,
value: DigitVec::from_vec(
vec![16568107915372457172, 39594627279977552]
),
}
}
impl_case!(prec1_up: round=Up; 1 => [2] E 205);
impl_case!(prec1_down: round=Down; 1 => [1] E 205);
impl_case!(prec11_up: round=Up; 11 => [12180455666] E 195);
impl_case!(prec25: 25 => [7055331922361162211, 66030] E 181);
impl_case!(prec_30_up: 30 => [571648947000381622, 6603038247] E 176);
impl_case!(prec_31_up: 31 => [5716489470003816211, 66030382470] E 175);
impl_case!(prec_57_up: 57 =>
[3586467374344137641, 14971304827359975165, 357951420621793766] E 149);
impl_case!(prec_75_up: 75 =>
[16970166308972310451, 15246513073646694077, 13267213422529722744, 19404585394121069] E 131);
}
}
mod random_values {
use super::*;
fn input_a() -> WithScale<BigDigitVec> {
let a = vec![
1745623865429447471,
9152528756446785169,
791242510259261833,
8695454801466577396,
8392994416015036890,
2912771882945679798,
8993891992610859856,
8294679885144779824,
8631634693823981953,
366928013,
];
WithScale {
value: BigDigitVec::from_vec(a),
scale: 100,
}
}
fn input_b() -> WithScale<BigDigitVec> {
let b = vec![
518171251856216712,
8211715648977239115,
1585852536764360977,
1552672896608399639,
1044291249247,
];
WithScale {
value: BigDigitVec::from_vec(b),
scale: -5,
}
}
impl_case!(prec100: 100 => [
7841754692876239913,
2960052148898606502,
16409584969160271562,
16913806906493283056,
14019529503395454758,
513 ] E 77);
impl_case!(prec10_rd: round=Down; 10 => [ 1097384700 ] E 167);
impl_case!(prec20_rd: round=Down; 20 => [ 10973847000387492259 ] E 157);
impl_case!(prec20_ru: round=Up; 20 => [ 10973847000387492260 ] E 157);
impl_case!(prec45: 45 => [ 14618765252943857298, 6989353086943465649, 322492 ] E 132);
impl_case!(prec46: 46 => [ 17060444013471711666, 14553298648306001649, 3224923 ] E 131);
}
}
mod multiply_at_product_index {
use super::*;
macro_rules! impl_case {
($name:ident: $idx:literal => $expected:expr) => {
#[test]
fn $name() {
let (a, b) = test_input();
let a = BigDigitSliceP19::from_slice(&a);
let b = BigDigitSliceP19::from_slice(&b);
let mut product = DigitVec::<RADIX_10p19_u64, LittleEndian>::new();
let expected: &[u64] = &$expected;
multiply_at_product_index(&mut product, a, b, $idx);
assert_eq!(product.digits, expected);
}
};
}
mod random_values {
use super::*;
fn test_input() -> (Vec<u64>, Vec<u64>) {
let a = vec![
1745623865429447471,
9152528756446785169,
791242510259261833,
8695454801466577396,
8392994416015036890,
2912771882945679798,
8993891992610859856,
8294679885144779824,
8631634693823981953,
366928013,
];
let b = vec![
518171251856216712,
8211715648977239115,
1585852536764360977,
1552672896608399639,
1044291249247,
];
(a, b)
}
impl_case!(case_1: 1 => [
3259170168870572493,
8530725771486096200,
2353601569174537990,
9915907985447408257,
5505012768436728039,
3337388859546710366,
1787670230149175286,
7565280555772427422,
7309104897441821141,
4201853743352582046,
9605931707432557799,
9324155135517901886,
3179713980940485874,
38
]);
impl_case!(case_3: 3 => [
4519975091742652829,
9915907985447408256,
5505012768436728039,
3337388859546710366,
1787670230149175286,
7565280555772427422,
7309104897441821141,
4201853743352582046,
9605931707432557799,
9324155135517901886,
3179713980940485874,
38
]);
impl_case!(case_9: 9 => [
8171925425020376989,
4201853743352582045,
9605931707432557799,
9324155135517901886,
3179713980940485874,
38
]);
impl_case!(case_12: 12 => [
7983943745001026698,
3179713980940485874,
38
]);
impl_case!(case_20: 20 => []);
}
}
mod multiply_big_int_with_ctx {
use super::*;
macro_rules! impl_case {
(full => $expected:literal) => {
#[test]
fn case_full() {
let (x, y) = test_input();
let product = &x * &y;
let expected: BigInt = $expected.parse().unwrap();
assert_eq!(&expected, &product);
}
};
($prec:literal => $expected:literal E $exp:literal) => {
paste! {
#[test]
fn [< case_prec $prec >] () {
impl_case!(
IMPL;
ctx=Context::default().with_prec($prec);
$expected;
$exp
);
}
}
};
($prec:literal; $mode:ident => $expected:literal E $exp:literal) => {
paste! {
#[test]
fn [< case_prec $prec _ $mode:lower >]() {
impl_case!(
IMPL;
ctx=Context::default().with_rounding_mode(RoundingMode::$mode).with_prec($prec);
$expected;
$exp
);
}
}
};
($prec:literal; $($modes:ident),+ => $expected:literal E $exp:literal) => {
$( impl_case!($prec; $modes => $expected E $exp); )*
};
(IMPL; ctx=$ctx:expr; $expected:literal; $exp:literal) => {
let (x, y) = test_input();
let ctx = $ctx.unwrap();
let product = multiply_big_int_with_ctx(&x, &y, ctx);
let expected: BigInt = $expected.parse().unwrap();
let scale = -$exp;
assert_eq!(&expected, &product.value);
assert_eq!(&scale, &product.scale);
};
}
mod mul_577874872717e492_696712038e285 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "577874872717466911184559916156758198495131305219358809343652669536302387743158062880956367761473177845712351639985492473123959095758451817231985325403278703100241171849679780394380997111752306496891336078616237486336807931580623365870368160556723018500080769313066709500174011587939745841025646291922884710337974681230011250190261422246454991091897190225976651017177719025146752407491035501139104790891684620162820417602920652689929206945524922873810759445524737158705885775589194963686168193817138671875".parse().unwrap();
let y: BigInt = "696712038660547059904752779034165119484624188403362872193018065005292090954487758438349971006124876297418423724096428714200094204277821355374358649621264188134962601815256767310343261823948242351360751280910536781247104655969073243119218479973070589731361603163735999605615737734639873901461504".parse().unwrap();
(x, y)
}
impl_case!(100; Down => "4026123806616905180553157364566020245817156933504926464873554931196880658239704482799527614035787776" E 698);
impl_case!(20; Down => "40261238066169051805" E 778);
}
mod mul_1442862119e445_1049464e105 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "14428621197889752189861398972981082461843826128512116303033203450866726426082853906596666646209600245865382634277766055876367040002473414960534339870779684891851540020597214991380071631960919603045037521801802725511393621544601218214902662462163496096667869677784522965589318809320143842055299565296240744974377213638202218555750884767181679713147685927591605307661717624963762005955819493848581352190387436454778284644628882915640133433043956756591796875".parse().unwrap();
let y: BigInt = "1049464598544894921302784839734515848195965967618699631485860068380390543981052363225912818001120911046454804480".parse().unwrap();
(x, y)
}
impl_case!(20; HalfEven => "15142327152999729642" E 546);
impl_case!(138; HalfDown => "151423271529997296423843423920943952557791563643246327643459830966880329966739641792530818647522102274133154353120322001711481566221946243" E 428);
impl_case!(246; Up,
HalfUp => "151423271529997296423843423920943952557791563643246327643459830966880329966739641792530818647522102274133154353120322001711481566221946242709348400715315872658516242116494741084148721184917688258189092970640993174313848612655419856309890747070313" E 320);
impl_case!(246; Down,
HalfDown,
HalfEven => "151423271529997296423843423920943952557791563643246327643459830966880329966739641792530818647522102274133154353120322001711481566221946242709348400715315872658516242116494741084148721184917688258189092970640993174313848612655419856309890747070312" E 320);
impl_case!(247; Up, Down => "1514232715299972964238434239209439525577915636432463276434598309668803299667396417925308186475221022741331543531203220017114815662219462427093484007153158726585162421164947410841487211849176882581890929706409931743138486126554198563098907470703125" E 319);
impl_case!(248; Up, Down => "15142327152999729642384342392094395255779156364324632764345983096688032996673964179253081864752210227413315435312032200171148156622194624270934840071531587265851624211649474108414872118491768825818909297064099317431384861265541985630989074707031250" E 318);
impl_case!(357; Down => "151423271529997296423843423920943952557791563643246327643459830966880329966739641792530818647522102274133154353120322001711481566221946242709348400715315872658516242116494741084148721184917688258189092970640993174313848612655419856309890747070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" E 209);
}
mod mul_11552262607819902e131_75e161 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "1155226260781990200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse().unwrap();
let y: BigInt = "7500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse().unwrap();
(x, y)
}
impl_case!(20 => "86641969558649265000" E 290);
impl_case!(18; HalfUp => "866419695586492650" E 292);
impl_case!(17; HalfUp, HalfDown => "86641969558649265" E 293);
impl_case!(16; Up, HalfUp => "8664196955864927" E 294);
impl_case!(16; Down, HalfDown, HalfEven => "8664196955864926" E 294);
impl_case!(15; Up, HalfDown => "866419695586493" E 295);
impl_case!(15; Down => "866419695586492" E 295);
impl_case!( 3; HalfUp => "866" E 307);
}
mod mul_2301346222e107_14293213e315 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "230134622236549555995211986626222699902919552403311068655782487235360869740373750138395520899795192776856789295000000".parse().unwrap();
let y: BigInt = "14293213600958985303333846898378944669728091790434135672846064625014252175269303162751477769546102012233954333273726511104485055758813349716438744379331517132722718015116165694607959258435272025702738339275667597501313358033107443840555382841970678973851997248262639615206455939322314712306500000000000000000000000000000000".parse().unwrap();
(x, y)
}
impl_case!(1 => "3" E 438);
impl_case!(10 => "3289363313" E 429);
impl_case!(20 => "32893633126030082513" E 419);
impl_case!(401 => "32893633126030082513378632456028104243338158146601751534822570641115861940893690474203736021657204584394456560452273117013862292944834269220913901434456366640765512794407601501204644375698772310462659595240672712968083946415944676232524453019368460583076233422452053267394081654933088569072574309446551869537537085955808336137944176420693881753901339121561334586231165213326029020686758979692139589175" E 38);
impl_case!(400; HalfUp => "3289363312603008251337863245602810424333815814660175153482257064111586194089369047420373602165720458439445656045227311701386229294483426922091390143445636664076551279440760150120464437569877231046265959524067271296808394641594467623252445301936846058307623342245205326739408165493308856907257430944655186953753708595580833613794417642069388175390133912156133458623116521332602902068675897969213958918" E 39);
impl_case!(400; HalfDown => "3289363312603008251337863245602810424333815814660175153482257064111586194089369047420373602165720458439445656045227311701386229294483426922091390143445636664076551279440760150120464437569877231046265959524067271296808394641594467623252445301936846058307623342245205326739408165493308856907257430944655186953753708595580833613794417642069388175390133912156133458623116521332602902068675897969213958917" E 39);
}
mod mul_166282988e757_855704757e288 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "1662829881972302555130573804034884736045567192245210098539333943847359516964532887814910330238584574704591142597582120739098300776070255016531228502052315027932433758655554089934478913134076538917555237055311466963257200943418192284685329544412527781851150111516400149208425751400577475249704818681525213682644230996369594895101870162749874014287967075708189893449815333186508386746072349175785274400940465234953370696338639401851764570625527530834473094592285942335138352231629223479010378029739170207319201385183107178796700474330961290205720379495017762115091196226436689486111860406277126830834375106428374156802498831754786978409114271376697671477362897657305451012544150393117399631804227698370258868601667565428070820650330308154707381618209183216094970703125".parse().unwrap();
let y: BigInt = "855704757901450759869356338513283551486583906378815084661323942969666040804246301726741288371813738860776552307977511102966634857016690379580472911872149121752146077285669707976656886280326152572122998172317660237359659093011810926589974967764428889136711853677544671180201059446857211098370670592".parse().unwrap();
(x, y)
}
impl_case!(132 => "142289144158440709930589101331424815642676467582494920860869705909839132157013788030340030454912181312465691007673740386962890625000" E 931);
impl_case!(63 => "142289144158440709930589101331424815642676467582494920860869706" E 1000);
impl_case!(30 => "142289144158440709930589101331" E 1033);
impl_case!(20 => "14228914415844070993" E 1043);
impl_case!(19 => "1422891441584407099" E 1044);
}
// test (2^5000-1) * (2^1500-1)
mod mul_2p5000m1_2p1501m1 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "141246703213942603683520966701614733366889617518454111681368808585711816984270751255808912631671152637335603208431366082764203838069979338335971185726639923431051777851865399011877999645131707069373498212631323752553111215372844035950900535954860733418453405575566736801565587405464699640499050849699472357900905617571376618228216434213181520991556677126498651782204174061830939239176861341383294018240225838692725596147005144243281075275629495339093813198966735633606329691023842454125835888656873133981287240980008838073668221804264432910894030789020219440578198488267339768238872279902157420307247570510423845868872596735891805818727796435753018518086641356012851302546726823009250218328018251907340245449863183265637987862198511046362985461949587281119139907228004385942880953958816554567625296086916885774828934449941362416588675326940332561103664556982622206834474219811081872404929503481991376740379825998791411879802717583885498575115299471743469241117070230398103378615232793710290992656444842895511830355733152020804157920090041811951880456705515468349446182731742327685989277607620709525878318766488368348965015474997864119765441433356928012344111765735336393557879214937004347568208665958717764059293592887514292843557047089164876483116615691886203812997555690171892169733755224469032475078797830901321579940127337210694377283439922280274060798234786740434893458120198341101033812506720046609891160700284002100980452964039788704335302619337597862052192280371481132164147186514169090917191909375".parse().unwrap();
let y: BigInt = "35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150406795437517399294548941469959754171038918004700847889956485329097264486802711583462946536682184340138629451355458264946342525383619389314960644665052551751442335509249173361130355796109709885580674313954210217657847432626760733004753275317192133674703563372783297041993227052663333668509952000175053355529058880434182538386715523683713208549375".parse().unwrap();
(x, y)
}
impl_case!(100 => "4954180389441794407302644533158844937036173071799942385207702899881096950794929284226174201155309760" E 1857);
impl_case!(70 => "4954180389441794407302644533158844937036173071799942385207702899881097" E 1887);
impl_case!(20 => "49541803894417944073" E 1937);
}
mod multiply_313313e185_140912e85 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "31331330514777647459696918012218766637269396231379435058341584170846149718531941093035596483272466942484919002494751588025494203950111183556196762802239021663296916615390846043521157975900649".parse().unwrap();
let y: BigInt = "1409125393389843319552855599302577071349036214812589000980540875883362915766473073232671889".parse().unwrap();
(x, y)
}
impl_case!(full => "44149773437063254678149469396251230458443452710019771114377331920312228495036605502543146558201981056772851870606187717471634519393139631393769297684773531284154562671396651882745113413784696354015721073630190690162770887707923095632780007819514677121000367593109419444597479155961");
impl_case!(100 => "4414977343706325467814946939625123045844345271001977111437733192031222849503660550254314655820198106" E 181);
impl_case!(50 => "44149773437063254678149469396251230458443452710020" E 231);
impl_case!(21 => "441497734370632546781" E 260);
}
mod mul_354436071780069e151_282138326095801e70 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "3544360717800690051921825754840028412915557760215486673759084471433756826848643934952495657908167389640789167410480517347773985344060322134315971203024120535921247142".parse().unwrap();
let y: BigInt = "2821383260958014531084804730393168953719437088977599878666724657220634716408631037763".parse().unwrap();
(x, y)
}
impl_case!(200; Up => "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999979587838286624448431722853801267006" E 50);
impl_case!(200; Down => "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999979587838286624448431722853801267005" E 50);
impl_case!(166; Up => "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998" E 84);
impl_case!(166; Down => "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997" E 84);
impl_case!(165; Up => "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" E 86);
impl_case!(165; Down => "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" E 85);
impl_case!(42; Up => "100000000000000000000000000000000000000000" E 209);
impl_case!(22; Up => "1000000000000000000000" E 229);
impl_case!(21; Up => "100000000000000000000" E 230);
impl_case!(20; Up => "10000000000000000000" E 231);
impl_case!(19; Up => "1000000000000000000" E 232);
impl_case!(12; Up => "100000000000" E 239);
impl_case!(12; Down => "999999999999" E 238);
impl_case!(2; Up => "10" E 249);
impl_case!(2; Down => "99" E 248);
impl_case!(1; Up, HalfUp => "1" E 250);
impl_case!(1; Down => "9" E 249);
}
mod mul_3721418e448_3844674e161 {
use super::*;
fn test_input() -> (BigInt, BigInt) {
let x: BigInt = "37214180020990129688144525415958680174157975522481928636541900907279612101437934903263895850798267657684166647521832553912867028735643169656904261854440137332351057065885513562123737325309196016024433700918100990040278606068777262035069231336055867161206731423272839919925319426271071135470308154818218588125994382305796706103307807638138902394400413759405500315832312273461261134673346351894542208780520017757692703697092184711436857469379901885986328125".parse().unwrap();
let y: BigInt = "384467472657945478705050171808793258461219095507172038645145218810507057013081321321499154743364560076819504633305258370960191863566109907922325021911311899034388627258125176177530017308946900981633538093921103514946225947524282186623225866254314533377160053778776276453031176006567736506050524284200740234201681989688527171382167496044598504125969423204217194885709731987591265467004291805188733436497695584275662479958826872492302565650006868261814480548258209741016215533270514872064920715433587381471128142127411378792338183702243894864240468654283770230621234327560844588972472126092496338279872812038026604640358131717471991285825660709098949913655676881776223568791337070502357370402925535826378792284995488461006043177936586374698890722356736660003662109375".parse().unwrap();
(x, y)
}
impl_case!(1220 => "14307641739707883586679338985784075376978599376076587159440407707473484422913380008679767889422355347578618773517358618682873816807001368824338399142290429730889921795132627329720311739245335457279882660403134178519487192193894827422017154794231967246548713182248254712192749435152248607256549045476459086684404679865181612177150422506682419296142751964295148026282623865246096746974909857474439409542650897431239188074724043848310873968922165900982577988822068956986831441597090874147542405989083220921853122209746471544669432201826149806457043393719329728030519620309220466905001009022724582301547918511296250822446396192324003728354373460047809727056243017571910340832631321081615757824717334420837535928747492488405758229871707378866111943107064677309884245984942614408304014573934636656429274910312463230088178109721849404398091245972145748205556337972593506762958354058055515482983023700007919157035627908661458407216568244912244912595573815702329952766665565695461070495291089051793343278543261429000685884437880347246913152237805580594025316169462092558252280687656044981784943452157349160827416439182889565322019088971898689733394885908687909675808992617947650750136428902947738350803774665109813213348388671875" E 0);
}
}
mod test_multiply_quad_spread_into {
use super::*;
macro_rules! impl_case {
( wrapping: $($toks:tt)* ) => {
impl_case!(multiply_quad_spread_into_wrapping; $($toks)*);
};
(
$func:ident;
$s:literal @ $n:literal,
[ $a:literal, $b:literal, $y:literal, $z:literal] => $expected:expr
) => {
paste!{
#[test]
fn [< case_ $n _ $a _ $b _ $y _ $z >]() {
let mut result = vec![0; $s];
$func(&mut result, $n, $a, $b, $y, $z);
let expected = &$expected;
assert_eq!(expected, result.as_slice());
}
}
};
( $($toks:tt)* ) => {
impl_case!(multiply_quad_spread_into; $($toks)*);
};
}
impl_case!(
8 @ 2,
[2559712337, 684026673, 1163340730, 1823138616]
=> [0u32, 0, 3001179060, 4203670869, 1059648540, 580714756, 0, 0]);
impl_case!(
6 @ 1,
[4294967295, 4294967295, 4294967295, 4294967295]
=> [0u32, 2, 0, 4294967292, 4294967295, 1]);
impl_case!(
wrapping: 8 @ 6,
[2559712337, 684026673, 1163340730, 1823138616]
=> [1059648540u32, 580714756, 0, 0, 0, 0, 3001179060, 4203670869]);
}
#[cfg(all(test, property_tests))]
mod props {
use super::*;
use proptest::{self as pt};
use proptest::prelude::*;
use num_traits::FromPrimitive;
fn random_f64() -> pt::num::f64::Any {
use proptest::num::f64::*;
NORMAL | SUBNORMAL | ZERO | NEGATIVE
}
fn rounding_modes() -> impl Strategy<Value = RoundingMode> {
prop_oneof![
Just(RoundingMode::Down),
Just(RoundingMode::Up),
Just(RoundingMode::HalfEven),
]
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10_000))]
#[test]
fn test_multiply_f64_decimals_with_context(
a in random_f64(), b in random_f64(), prec in 1..6000u64, mode in rounding_modes()
) {
let prec = NonZeroU64::new(prec).unwrap();
let a: BigDecimal = BigDecimal::from_f64(a).unwrap();
let b: BigDecimal = BigDecimal::from_f64(b).unwrap();
let a_times_b = &a * &b;
let a_times_b_rounded = a_times_b.with_precision_round(prec, mode);
let mut dest = BigDecimal::default();
let ctx = Context::new(prec, mode);
super::multiply_decimals_with_context(&mut dest, &a, &b, &ctx);
prop_assert_eq!(a_times_b_rounded, dest)
}
}
}