mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-02 11:12:31 +00:00
261 lines
38 KiB
Odin
261 lines
38 KiB
Odin
//+ignore
|
|
package math_big
|
|
|
|
/*
|
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
|
Made available under Odin's BSD-3 license.
|
|
|
|
A BigInt implementation in Odin.
|
|
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
|
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
|
*/
|
|
|
|
import "core:fmt"
|
|
import "core:mem"
|
|
|
|
print_configation :: proc() {
|
|
fmt.printf(
|
|
`
|
|
Configuration:
|
|
_DIGIT_BITS %v
|
|
_MIN_DIGIT_COUNT %v
|
|
_MAX_DIGIT_COUNT %v
|
|
_DEFAULT_DIGIT_COUNT %v
|
|
_MAX_COMBA %v
|
|
_WARRAY %v
|
|
Runtime tunable:
|
|
MUL_KARATSUBA_CUTOFF %v
|
|
SQR_KARATSUBA_CUTOFF %v
|
|
MUL_TOOM_CUTOFF %v
|
|
SQR_TOOM_CUTOFF %v
|
|
MAX_ITERATIONS_ROOT_N %v
|
|
FACTORIAL_MAX_N %v
|
|
FACTORIAL_BINARY_SPLIT_CUTOFF %v
|
|
FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS %v
|
|
|
|
`, _DIGIT_BITS,
|
|
_MIN_DIGIT_COUNT,
|
|
_MAX_DIGIT_COUNT,
|
|
_DEFAULT_DIGIT_COUNT,
|
|
_MAX_COMBA,
|
|
_WARRAY,
|
|
MUL_KARATSUBA_CUTOFF,
|
|
SQR_KARATSUBA_CUTOFF,
|
|
MUL_TOOM_CUTOFF,
|
|
SQR_TOOM_CUTOFF,
|
|
MAX_ITERATIONS_ROOT_N,
|
|
FACTORIAL_MAX_N,
|
|
FACTORIAL_BINARY_SPLIT_CUTOFF,
|
|
FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS,
|
|
);
|
|
|
|
}
|
|
|
|
print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) {
|
|
assert_if_nil(a);
|
|
|
|
as, err := itoa(a, base);
|
|
defer delete(as);
|
|
|
|
cb := internal_count_bits(a);
|
|
if print_name {
|
|
fmt.printf("%v", name);
|
|
}
|
|
if err != nil {
|
|
fmt.printf("%v (error: %v | %v)", name, err, a);
|
|
}
|
|
fmt.printf("%v", as);
|
|
if print_extra_info {
|
|
fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags);
|
|
}
|
|
if newline {
|
|
fmt.println();
|
|
}
|
|
}
|
|
|
|
int_to_byte :: proc(v: ^Int) {
|
|
err: Error;
|
|
size: int;
|
|
print("v: ", v);
|
|
fmt.println();
|
|
|
|
t := &Int{};
|
|
defer destroy(t);
|
|
|
|
if size, err = int_to_bytes_size(v); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b1 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_big(v, b1);
|
|
int_from_bytes_big(t, b1);
|
|
fmt.printf("big: %v | err: %v\n", b1, err);
|
|
|
|
int_from_bytes_big(t, b1);
|
|
if internal_cmp_mag(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b2 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_big_python(v, b2);
|
|
fmt.printf("big python: %v | err: %v\n", b2, err);
|
|
|
|
if err == nil {
|
|
int_from_bytes_big_python(t, b2);
|
|
if internal_cmp_mag(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v, true); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b3 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_big(v, b3, true);
|
|
fmt.printf("big signed: %v | err: %v\n", b3, err);
|
|
|
|
int_from_bytes_big(t, b3, true);
|
|
if internal_cmp(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v, true); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b4 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_big_python(v, b4, true);
|
|
fmt.printf("big signed python: %v | err: %v\n", b4, err);
|
|
|
|
int_from_bytes_big_python(t, b4, true);
|
|
if internal_cmp(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
}
|
|
|
|
int_to_byte_little :: proc(v: ^Int) {
|
|
err: Error;
|
|
size: int;
|
|
print("v: ", v);
|
|
fmt.println();
|
|
|
|
t := &Int{};
|
|
defer destroy(t);
|
|
|
|
if size, err = int_to_bytes_size(v); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b1 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_little(v, b1);
|
|
fmt.printf("little: %v | err: %v\n", b1, err);
|
|
|
|
int_from_bytes_little(t, b1);
|
|
if internal_cmp_mag(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b2 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_little_python(v, b2);
|
|
fmt.printf("little python: %v | err: %v\n", b2, err);
|
|
|
|
if err == nil {
|
|
int_from_bytes_little_python(t, b2);
|
|
if internal_cmp_mag(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v, true); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b3 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_little(v, b3, true);
|
|
fmt.printf("little signed: %v | err: %v\n", b3, err);
|
|
|
|
int_from_bytes_little(t, b3, true);
|
|
if internal_cmp(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
|
|
if size, err = int_to_bytes_size(v, true); err != nil {
|
|
fmt.printf("int_to_bytes_size returned: %v\n", err);
|
|
return;
|
|
}
|
|
b4 := make([]u8, size, context.temp_allocator);
|
|
err = int_to_bytes_little_python(v, b4, true);
|
|
fmt.printf("little signed python: %v | err: %v\n", b4, err);
|
|
|
|
int_from_bytes_little_python(t, b4, true);
|
|
if internal_cmp(t, v) != 0 {
|
|
print("\tError parsing t: ", t);
|
|
}
|
|
}
|
|
|
|
FAC_6_102 := "289BE8D277AAFBEEE05072D73DAB0CB188DD578EEF398C7BE4AD105965CC224F04EFA7E0D5267C117B276A336BCBFB948A4ECC691FAD1BC06265385D9D75404AED9F52A5DE6C29085D0656DE4D8B26A303E8B97D68C32648DAF1BECC073A7AC7B08145B0790E323682AB5A4A7D08134F92317C9A66C6EC3F8D389B72AC2270FE3F39E3C582F7C258A95CAED677313A7D9B167D212D3D3501A275EF11A215C1AA7B2D9793801C9C71AE5D07F1A43403F3BC573FAB54B69ABFF16138AA17661C5F41D3BEA2822523C89294F93C4A85B760DF6ABC27D46EA7ADCEC61BE13B8F57420F225CCAFF32DE2B2C2BC5C43000A93E770A148FED76886C79449D692C980C64DB590B754C845B31FD6A0011815B701541402A56F9A7140FB371470FDF167FCEB3DF30DA38B01A979CEB78034F62B82E23A3595D6B4893EF32E70969BE26EF36D66FB6EC2F051C7BC74E842964DC5CA0FB15457939B89E9E90108D0F0D8FF1BA87FE566170B32F2AE241C85A782AAE27602F709B46F55B0FFF9378CF0BE763079CEEF09422B8F67D897CAB87887712E42FEA9B743DC72E78D24F73BBBAD146F47078625FE108929A401A69D35BB0419B54283C274F04B683720B88D7158B9EFFA3D26321C94FD70E4F0BB2A847EBC0A77CDFAB3C66A1A4C022B6354FFFF7D8A279F63531DD2BAA32233ACD3109AF489A8596B19F5CC2FFA1BB49D6BC806C6B9880BFA80E01A3CE43053238E23D9C88A8DD184BF3B99C366F76DE0E0276F389C07F67DCA36045CCDC73E6FE8E6BE8679E351547AC7E4D4FA24B92F0870BB3D7E777F65E5230D6DD640118F7ED471A929511684147BB97487BF8BB4621C63D0B7A3BC9C5BE316118B269F2C4BE996D173C1740CC43C276758B3BA5991149D6DCD76910359F7FE0459C8D255A0CF6982831FE3CAC9D7DA4C074C5FCAB1631AE2878C4CDDF667F8DFB4D81A1D7C2B578A44BB791EAE14BB380098F971A0BA27941392804F8741BE28EA56CC4024BB48033376B8223DFEF075B6DEC2B2602CBCAAFB9C72FDF7933FC8BC48B1AEBAEEDBF3621F0004911015EC4DD4BCFB6F9708A293E12C39B2EDF93B613089AF1C4F4A812B9CCAF57C2CEDAC637D2688426D6145FDC2CEECC589F2E75AB560F1BC991DF28785440E00BA9FA8CE5CEAB43AF753BDE88FA9770857CDFDCF1E2CC6A02D4860B67F40F9FA6B4E0F3EB8C17A4843569595156450519B011826826642D9AC43575914BB45F5A5C24914BFC9AC620AC067E8603BC56E6B3B863F5C29393CBBF6AA72D6367FB47EE996890BEF7D057BBAB0E54203B0147CE2BD3105A322408ADFF5BC3FB1ED90E3B14CAD6DD25E18AD358577A7B58FA19AB6F83F5CC8A2C19E9E5CFC189C727F7920C1A059537110EA2A7CF27D4F9A046FC8C43291CE67BEB48FF589CA191AC132B05E54DE0D019B39F9C792BCF9053CE2403901BF660E9EA681C8A2DDD014F2B024D6206405EFEC8D9DEBB9EDC31B49AEC6AAF76FFC5CB130AEFB3125CBAD951E6A67534F7658330F62D28D8BE3B1D7B5290B55198129B8BD8E01FC4070EBC567A33D7693269AC7BE77CB44FD2E2D8DE2C04129FA690094131360026EDC3FBF658B3569BBF373C5DA19C7AD20A31757ACEFDB042BEC0EAE31ADA3346028854D81F6B7B7C7B44F2B97CAE1894F564AA29648DBEDCE0898F6C3F6B0800ECD4C92F659E659FC6D5B248FAF627DA467232C1A890AC21212471ACF307514593CF74516F130C9ACB435992385BC6E41AFDE84DFC2CEFE28DDA482E358BB65FC9A289D7315E399B044DB81B4719D5687E876DE41C5AAE28DF0539D61BAD53A57066EF621BFD6E373DD1DD86FA167A731982A5E84A898CC5A7A9FBB91753FF5DB62113DF6A6245AF72198D6059BB75F4F63892D40A2A1C78EA3B4949E8AE7BF344A8E2A3964E9701C3B66C4989A1090107388B6A29736C90DE652C924CC6C055DAABD2CACEE145A4F7772442BBFF938AC4D5F6266AC7301D36E9E87074CBC0651ADD7EE5D795E8956E512CC63D81731D5B7FCFCCBAD254EBDDBF26ADA68FFBC8D46481512B4964ECFEE1693C4AFB7505FC60267E0C5D613C89D210AFE1BE718DA5506424A5D9D1035A4A68F8D24084FC650E9D88BD111DA838A24E15E38B5417D9B108EA1D597418D1B659EDC4C9E3FD8E7FA10C5F1D97252A3BE3FC3991CB8E88DBF0BC2E5612B36152B67B9C906BC5179712DBDFBB10ADB6B3B7E946D9D2F224F80AB01DBB558959CEB8C1A5549F8FDB10CA2B6F0A267EE317B9E02ABE9B628A2B592D5C63794E98F6E1943DD9A644D136007BF5D1CC91A7F2D7E1BB7BCECDCB17A1ABA3050133B8218C76664D2EDD1714206C7A31FD943E0E03D37222733E575D8BBB24743FF59D727C43DE4F7A5F311A4AAED1DB314D11D10212B61005817B016BBAB1118EDF434ED7C9C8B6B009AAA89CC21614D24A21DCC03C59B6EF06A6653EB55168FE3589B6808BFCB86C91453377C6D7691C364936A53C15F6B8169B2A033E37E7F07D68C2DAFB661B0A1A9102B46B46CFA5D4958FF569C5F11F6859893FF972B171A01AB93ACBEE832E300F88C5383D818F0A4F4C084331050EFB23F151F2C4FCC06816599597DC7BABFDC1C04EBBB06F3920BF45FF0B7C317EA51A41715FB8AE2ADAA6330DB6E268106575FC388D50BD8651D2FFF4E4151D529727C4F29D3E6A460230B55B5B020B87F2A3F710F16078AFEEAA34652645BDD24231A36B461A7657978522C1CBB0D68CB1323C8ECEEE07720A95529EB4562653EED6DC3AB55439F38A9C3079F7B6A2AE807C70E5637C5C0E2CAE92F5CDAF4A14692892A4E7006A4EC7D754E710C9AF72A248CB02EE69A7AB2527322CE9ACE1BC717B268B342C601C0A45DD5AADFF326980657B40B97DA832F3B79260E4BECF5F88EBB2E23514B1A84B785E80730FADAAA412529D5E64D32B20F72BED8F2FA78771E5B754A2BA8D6BC9FD98A9DDF48A5AABD00BECD6E9549F0E0AD51854B701A3AB40D77BDDF3A2833FE1ABE1420AE663AAFEED794E32F16E005257C41EDF95CAF818248DF8BBD952D12DE6DF3E7FFCAC8F5C57B633E6EA702BA29C468CD4BF289FF051EDA4253FECD2AC47EC1E4B1FF3FE72D7DBBEC435E72CA521E75CC101F0FE4A687FFDEA4ACF3405DAFD84692312BFDC238E2FA73388E3068F7D5A31F30A736AA882833DDA7784B036A169716764BBA18234082AD9B5499592242EEA92A78F4C1BC73FDF8FB66AC80E59E6434F2D024F3B9833DAC1473A3F4EE1DF2753B0EF44D47907C9EC5FE321A2317A9DF937ACB705480AC0512900AB4D64679F41324F35BB2DB7714B57926E7D5CCC391B90DC5B300C075214741252A48CF45BD18E82C4187A87F95B766C966E4052030B1F6436B028566B2A020E36988D37BE8579E87771B9C47336319F8FA3276B9C67649E61B65BBA76D22DF87CCDF91E6FA28449AF25D4F88F1A4C9C69C1F75CB49FAA133B8687213FEB8C9C308D8DD997E257483EEC23CE61A1C273F006F2CDA65A8371833A2CD661F467BA6283DCA60C1708F012F0BDEF57B6616AE26A1B150AC8A97665FA6530DABACFE44B4B9A1EB26FAF9A0BAD06AA73F05B09DCA013AA265B863966C45B93B2DED3A6C3679EFC91EDAC887F7FAF8ABDD7C34DCF5D9B34A604512C285B62CB6D2C29743AD1281B59F4B6565E35F644998E0E7AFF7F2E3D86A20F15A4915AEEB8F4E25CF94C98F4E504CD8487FA4653D6DBDD2FEE4AB64966C94C99E91859C3BF7C0D276DBB2F09671A212E762C4744A263D21490801A4BE882C845D28DF2020E5DA31BC79D426E02CE22B82947516B4751787E0087D800CFEB2F804BDF4EF563F50C8215486BAD8CAB675DC1B0174276F4785D2A8E7FFE9552BC967F7C5FD363BC63E466FEB9587F36131AEDE71A3107E2FC2FD4307AF98664F32EBA32D60D0402DEE9051CAB154F365FB807C343F2E3041D84627411EB02B8237E8DD2E4F82C6DCC946266F267E94D73E231F07D000085DEA4DBA1F98606E8EAAEBE82B323E1A35EB144C2F97BAB9749932FD552B8279CBABD27D821CABEF906C364D0BC41D59A6B3BFBA43DB6AC6819FBF3A1A155677835375581A3A50F4801F655BDC470B7155B3367F75B014E9ADBEFC2D2DEFB4E830732F37F48312838A9951277ADCE7E7EFC187D7B1EBD3106A1DDF4FF45FD2260F88C5E17F2918BBB9DB57418DCD4FA1BA81E582C291ECE8E726D236C7E568DDEF266C14D68543FB8B459F784D55AB3569437A3E3CD53D98A9FCC5857627A94EDE30F30618A968C34AAAC345666F8F090AD9119637D3A4BF866FC05E2B5D836A9E8DE0EC98A67300BF7519EF39F11A146811E702C3D161771F1D03535D1C8FB3ACCE5073F4E109217492C916F8A5204AA7712A7B9BDA5ED915F930B510AFBCA616A064DF38B478BDF409A28AE00D263C95040FC5145B9EC37ADA6B81384EE90CA5934F598CBEFA62877618AA6FFFBE090AF2D39ED664F4898246C3AA75712A6348E0442CB7D57EC4DC8935889C7580E3AA8C3DF7B4D2FE4BC1174BD5C68E9FD0D59E49FC8D04A807EE1CBE883C7E1108D65D0B7C94928A798112645BC492EBA7DB04B0696838202DF0874366156D533A197C1D329CF160A45E1069AE1C8C9F5F93B26AA796442BEF76F55BE99AAF09B34B212EAD7E8C1CEDD7384602B8F795B8DBECA7F2B2FE01904952EBB64DAE931ACAE4F94390160E34B18D953935118027BE4D4422DA60112CCC7F4E1CF4C813F73E65584DCD6573FDC987E46696B2692913940B50340AB21B4B5877B4AD61FE8188E1D61C08558D4EFE2ADC9DBC451FA0DF97C5ACA76D8F4112C1A91D8307D0B8F20498E0120A394F5A303287DC02F9543909C84B0407C847830CCF0322B8E42989E602A3CD555CDD92928979BFCA5BEB69437E258EDEC34F4E9012FA6EEEDA9C2A3D3A0685B85215FE3DA5E6D046681FB6960A67A5C67D7C7485F1466C88F84514984325FABC44A0EA128987F6669F3A6D75B1B9E3FF34DC75BBD4CA8B435C0D6B6BC4EE916B0A1C901515D547982BAA6AF9ABD23B2044966823369E877F7B9FAF054EF56563EA1F0455ED2B089745FA8504D5CD800ABABA6C9E809070F8E53E7AD5A451573F8DF95BD6AE5C53F0CC8CF96CC45EB49B80295B4BE1DD1898F6D3C5FDC29D440BA3E82A530F2BC1FCF9ADECAC30A650153338536C4F2AD8D45E35E86860C68B5054CAA9ACC1C63676235AFBA8F97DC2C6C7A4FE6A09196F958BAC58185869B9C86993C1255B42D999412EF1DCDB3F22F94AC5294D853AA54D99C90CC8DFC4154044CB04241F56241F92B9DA783D5F7B91850993E7C3A77265807B101C02C5BB9E0C4146E5B38CDF1C1F5F76D1A25076F89ADC2A288FCA3A3A0827FC26704B7FCB45372173B972EA8769350DB94F34D28C5DA6A1FD69BEF66CD187129EA1786C652099385E65F19CBBCDFA4C6F30BE6CBB4D85818F552290E7D105C026E974E35474436C540E97710D50BC5B868D31474AEB9103FC9D7D0C2AA463D9B9209C01497B834144D9E9B191A7AE42D9E6591A6B2A868184818F9DCA64D0FD266D513C8D38D981C1807203865723EF327B87BB9CA9F16B68895DA666A4D134E234D18EF648121A1B375838E679CECEA7D6840BFF204D17F7369644D1B872E53002CBB9B53F87B17FF69C27B5524E7FE44B1A21D85144D16509C011A286EAF8242AADB8644BBF3CDBCCEA27046B23BC4FE40C9665F34343235D680EB04BCFE0EBA873CB8E882CB1B2DFC4AAF0FB2CC80EAF1C1D368B5746A6BCB9296E435F6D2FCBFAD6E9669E02BECED4217A64B1C0E9E68C53910FF332B6903F6C8843BAC2B9AE5A52E2F982F0705C521C19CCB07A7A2C0FB0904DBA2611E0FDBE2B822E3A3C516DFA8137E531ED11404559C5294410A31AE0ED1EE206829BF33F740E9CBD0C0ECA5FE7EBE0E9808435DA6BC5DB6FAE3A2B79766EFE4DE1ECDBF0EF011C2ADA01DCEF7368BFFA976101C759E0CB01919AF7D1451AC274CBCA48BA388F1E9A4FFEA3A3E6EF00EE0770D46047D4DEF577EF28415E22A127426DC86DCBF6DF0322C4BC1DC1A8D94DEAA804A23F4E07ED27DD1797F8870AA74B3BE10C31378D5FC4BFA942A9ECDABD2C27B1E141FD9C5B783406EB54058553E3A1717208041D39488CC44DE34254513A885C8F81829A639FBB5CBF0FB598A6604C1C0B849A9AF4E11EDDC862EE55991317AED6E3E37AD1A7E7D8354A5DF250CA95124705C1B19157E626EBC1FA3379C1FCFE1AFA5E9AB7253784BF1F6C1A47786003BD5430892C9B9EA3A528B7C28A75AEA049C50F02F729AD46AFC14ECAD36CF9D473FA29FE49CCB55001F2B25CED69FCA7F840C4768E0D1003CB698F18D848E6DC7D288FF30484D518F6509F2B63C30886D9EFFA08890F7B15C2EB9B025037FAC6AD3884D50AA2A007F36040C48A8C54DC943E2C5A2CC62440ED556344EEB66AA9F70A816712511A57BB4A78E7E5610B49C5B6B4D1BCCD1DF6D951865B5602295258D285B209B6E0CA9DEB716C59571A475AA28531EFC4E9B223C93E6CFE4A488059B773560EA6C7F843A19A9D2CDD1F3B4FD2F99AA91FA4F427C619E7D93D6D2BCE0253493D62B1C743451EDAADEE045A0C3F949E5EF87FBC9170E3FB48A81FF2E7DFA916607BF3020FC6C5332745CDA65E385A67EB764EA7E8532D537E6B933C3508400F10B8AB189B845D24CD96E9DDC2C2504CE46FE9BA986751AC76400E1C3DE4EF059D271AD8564D43860148E2F7D226B8AB13AB7B7E880FF013C0A3133DD9BB1747737C450B31593CA426C7EE79E8B16790818FA9BE7365510966E5095E2BF2ED4B6B66E36D2FA5158457C37E840B2C83BF29023910785361963EB8A2FB310C1C8C3001AFA04A34B86654EA639C413EC88F3C8CA7714F55BC89386C212EC3A77AE253D6F58CC46192CC343BDCC88D61EE7A65FB0B947FAE2BE25FC0D2C622853FF9D14C8745BBE1F5BEA70D2CCEA9885F4AB378E989B3DF05D5EB9928586258C07F977C701136E53AA67C9DD92FAC6917D04C593B7D9C1B616CF4270C6748D7776911213AD3F43BB36408BB0BFAB9C52E545DD79A5C4BC551DA99F0C6F4289C4DC6A74EDF6B1B5BE3F85B57BA8FDB89F5B1689A5596B5F129F5752CFE6FA1B5476F571B94CB534FF84A6AE4AAC2F5449DC0BA0E4FAF81BBD2D4710016DD31B4D9A7D683D0A848935C5FDDFC65AEBC113BFD7B382B08B5BA25050D447F29B048751DEACB1C672FC1BE103F4DFB9FFA02F2203349B64CD9485531637AD5E515C9A0FD917E74FC89E4B4292FCF8B3B4568C2157C4E72C6F45455B14CEB229D147C1C12E43C603888A4BCDD88D14208B96550C05A7D5686A7902A35F6A73E4BFADDF74D4DE8BA3FF00AFC0719ADCF410DD85ED9E0985DE0CD835560A128AACE3603EF4260E45C2DAE6D3F2EDCC7702DC03A50848FF6F8B3D806600A8E4EDF592A42FB36871C48CAC4013D9ADE1B48136A04709E9CD961138FFFAD7DA04C54F4C0C12688809186CBF40DC60E324516BCBE0B83F5E3CAED50A36596B272A50C99D66D7714AEC21D8296525C1D5B3944EF691EDD26BFA53B330800F937B951D071594C1638A533547FF6D386059F616B52F4B8762ECB394CBC28EAE79E620EE275ACE29AEE5F0A6C09017333106D4A042C6E917903F98F3891EBFDEC4E9A75CF0B415F581AF023D7F27FC8AC99DF1D0E1222C26254088E4B5A3AB21982A59010E92B7819B11D3A92F9DB58CD27CC543A890EBAA42BFC93132419970FCDBA126048DE7D41C3B4AE57502FFEB166FFE560F8203FE877A1529C2AE561EB2648B4A62DC326AF175DCC194E17A0F2CAE55D27A2D05B6E1F7922E65418B9E84364DFD5D192EB8BC626F3767E1B89E0491DD81A0CBB0D5B418B37733A520CA157BF60161A39AF301663BF38A2D1D020CE1DE1B63BBECA6DF45F7092D2982800C0E52F86D42884C8B079588FAC3F51D9CD7ED67518D888A39B6B5DF775E7286470063E5B944A1282882FD0E863799B63E6969A91D214C67DB8CDE1D648BEC0544CCE963F4B2C35E7CC25245205062D2214B619F506E2A2033AF3760AE4C495DE3D404BDAB2F21E4C2B44CE67DE04FC97DC3B2247D9602324E285D3296171D25530E4413B4E1E60DCCD45BB8A412825E98432D619F43B5BC7EBDACA0DA0EA429577F77A7524A61B46C41B0FEFBF99692D46EB0FEFCDE1A204922AA1EDC24BE15AE4B44B65AEA1CBE1A423376F8B336B60F066B3C8DF517B44A9C049BF9A2E580D2B050DBAA2AF596D7229143145E8E2323B7387EEA4951F2990CA597F2B247312D52A647FD4F5A7BECA11DD97C6A036C77116AB11C1D2FAC5E8C77FA7696D39ACBAFAB0F3B1857B24E68B0185C08964C12EDB855590F5E2B1E71AE18ACA37451B06DB7F1CB9F356F8CFFF27379AFA019611EB7E2C02DCCB0C4CD61C2B3628B6D998DD096103F46BA223921B30E3EF5FDA6ED6B877F759486723F4890DED6195574181066D5121901BAD731B5B6E66E66F3755C553F7DAA35C7A410D762ED160AA6D6487B2AD48EE75BD5D27F36920CC5541603FC9525A5883B85648C90717165AE20FE491EDD0F3FDEE6DD4CB2D3628ED2A47BB76FAAB459E83AFBD3AFF0B000A1EDDF17B040DFB2120A39552CF60C1668D26A2B87AD243054FA76DEB92BDECF01017811EAA78202BA144EDF7585939B02A6F652FED9C4084DF31D9A1FC2C70A653A1181F648BFEB20AD67F2DE8303699264561BA94115D3946719DC043C15AA6DC08D94F4F34D4713AC6FCA82ED31A83F8F1954EA38ED6B33AF55229DC068596AC97D99BEC4BB68C89C26C54825C9D6F9E1326EC67F3771E40228519D0FD8EEE3DE0A90F1684AE65F070AEF72AFC3DE1E7466A5BEDC356DAA69AE8A3973041F798AD31F50E778669D10F78DD1AAAC19BB6F46A7E5ABED22BE5AC69149D0AE9EFB3BE1C6EE89F1E30C28364BA297FEB283FB9D8EC06A46F644072AFCDB0C9E1815E9ABE75DD5A23153333C8FB2B00598ABB38A9999E4A651C58EB73C31F3C551A962535F2F1701B78DB68D20FAFBBA413193946DCC97D724F3F6BA3ECFCA2578DC58024F8C06776E09150F6B59DE166E83DA91739175289588296ED6FDCA75FC58D30C94183043D15A2EC04EDD249C4C1852DEC91BB18B0D87FABC99FE8D94AC804E1D23E0D0837BC7E5A84DD01F9CDD1EA1188F4D829B1A5B1E973B83A82CCA1E8F9F272449EC96FF1735A89451BA67B33493195CF4F26A0AB641BD8710602AA113F5D16F566658D37C0A4318368F9A79F0FC7AFCD4F810CC575E36972A5BC05C54147A90DC19572FF8B3BB255E7D5F5F96A6EA0742B376202EABEC9D3D97F519C40B1F0DCABBA4DF269A2A96F14445DBBEBBE0759B2FD02C4AF2174AF89988721238356F6ABD0B0196D0846B16D16FBDA47D3A77C96C43938FD95C1EBA54DC062E57A8E41D2130B990CFD153A64759F9F5A8148850BBC5318E760E4BA9127E46DCFC6091E02915B30A2437F367C01EB18DA56CF3D893323ACBB8D6F7FDE817819DF034AFEEACAD630C175535792621F9285F8A272D0CFD54E8E64362E56D846B244FF1F7E75A1646F1C693D4DFBA1B75B1BDF52927FB9F3F730F0910019A6F59BC79F75C7E1F5504A77227D5FF96E117460D8AF1B77D4B6C391F3ACF4CF8A6D10C91EE5A73C70327DDFBEDD8A71943E5467044B068F82739447275C624F8C019EE0B3EBB339759209AA6EEDC0C969E1D169D58B9D2508733F7056AAE62F69CAE671B5979E8EE73FF2CFA1139A6039FDFC048B2AAC0DF3F16A2CDD1BC375C1D545FC58CFDF7677ED45AB4864FCC0E23B2F45D251847CAC2AD8A285251FFA6E6035AA0262120EED993B9AB188815EAD21AD7BBAC847C73954AF1B8723E92BAD0E5CA7168C38AB2710A5D0C62FF01C4E422B5E9893A38EFC9898A4FD7D18FA15FDF3C4293FC774B52E58441463DE07127DE873D765F7B56AC3A783F27E611F80B69037B7B6B42980046B75DBDFC2E3717E0F2B1D71F876A2353953D543E4BEF17A60A9A9202FCCC36DCB5A688509B2BBD2DBF9EE5226580364DF20D375F866EB899A1F6C66783326B59439A4C3D75CC2A74F6917FF4DBBB7830C451D82679B9FB5D59FDC28472A6A00BB1167322770D3352C8908D6050F21E5818831FAF94C511777E0008742D7B733EBEF228E0289B8D88750FD3B854D0D66C82EBDCAFEABBF68FBD0BEC7C763F9589C7F6D66619062CF8E75E5C06D85450A5AEF82979D977FBE101E0E00590C7D6D2C46560E9F47D200881A7AB8CFA72C911B1F854428495EF0FA556E41804ADB8131E10160E573D3157F1784E343AD536A32EE3E3BDF50586A7CA091FF6BD579FC7F7733B14351446A0C1384B00AE0D1539CB1DDCB2563AD86EB1C65E92055E6F6FF516F764A0CCB3BF852687DA0D9FDE95A5A102D74620A2582BD70B35EE2C9CEE96D0043C816894D600DCCEE364235B133DC74DD9FE67C39E18B6EFA31B89C46F9B23A63F613E7E0EF822A83683BEA8B0F51F44B7C385FC38719B251A393474D2085F0A55EA34CC1D929C87E3EEEC942260429C354FD6241E13CAB48E2DD485E2D715171FFC1869A6846953B5727916C8402A0650121ADAC506F39511A2F5680DA2EA5C5C7C5FD6C8918885932D5BD2361330369F82C7485445F85146A636B9B9334E74D8C43E3A4E9C66257719E706DD57C56016DA9E390C1E447AE7653A2A0A6B0858A88DFA8B84EB262F022CE583C3EAA8D7B73EED6D2A246031E5F3ABE6CAAB4A00857A8C6404D325C8B569ABB224A4B500D9DB313EEBB5EBFA0C74017897F9B288B2DE707996D770CCF6F48D18FF4AB2523FD6BD886E02BF4BA0F413C93BAD412F2AA5A9E3C8DCADE6AE0A788BC326A75F6ACDE764E6F89D236D6F776B16DB80F3439FB83550C63FB4A4583E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
|
|
|
AA := "7e1c0f3c530239c47c1c5e891032dba5bd96e8d1fa32270e69640b3b6da7c8adb96839d072a163855b28ae60cbafef459add4ac7cc4c5111e851f154249f7409837867bf3d2574a0495be80a9c9d305f7f5bc7802d2c104ed297234e672a1f69eef05d8c28d04afc0d1b77afa2bfb09905631688fcaa5d5930e5b24f01e8515f8dced9953b94306b6066911868df6fa668ad3aeb49d3a53e93e0b90de64a27f1d5eea7e21fc71b7d3b4ca92798163a32b6df83e760a826fc71666e5301a4a14ee7fdb995a343b1d98a3bbce96261c2c923f1d0d2d1c16eefc5289daa6e7c116377e0801eb9dd407b490a76dd5b7980243a5a48915037d2df32f8ff356cfd7130390a71a2b37a4ca89515718db7593a4585d0901b7e84d39f8af4b9af071f441d1653b42e2e397c9c83f667041c94c8cf35b57e2d2c6f5293935da575bacd899ea1832560802d7f4b1b06cf55b2e06151a6eb0fad2dfe53d081b652257c75e07816fca1e8bdae54a8e33eaae327e659f376b0f27c8958eb8920c12318f4646ac529cdabeafa08ddd403a06d50918efa34701de6a74d2623d3492214feb10a88822bbaad699a4c3cdd14e1f5c0996ce7b4f5ecf98d919af3715e4ee12da37a883b4568ab69c61614e04bc649ce0f176773907c4af26324f78ad39639cb97fbfbc27f972fe4f2d78418d3c9313ba0157db3838bfee7e6771a682bf61bf15d440da9f1d16a79638460ab080b425fc1505d08213c12f47d925f7a00d1fc05fd2f4b834f35c3e933d24dd1d5167823cff1d04101bb376b5950073b0e4d4d6f76d9a6118792ad071775e507d224d032314704f1f7fe73b26e7c6ff2de5989900080cba339028a854536f024bd03e3b01f64b105c073a89952eae97a49140fa52018b8069100727ec01c3a35aa3fe96f4ea012fe1d840e205a75e109afb84fb70663629dd6d133e0ed86f7ea27c5d49842e98edc13a0c795ab98baeb2fa4ce1fb3c66261ad1d702f9ade91905a0fbdd5fed483e019a7858fa88a17204b55cdb6ee89ed62ed1c2805a6d0fd1e761d934e13357726e088fb9875c3fa44b344408fca5086114bbf94a719bdf50a65da1a583bb8402242eca51161d40ae64ad6b166f538362402b13cb5f6c80e24c8cf1155fdd4a574d1693c79900acdb4a298b2a51a33e60cf1bcd18e937feb91c8891decfa2895d2be776cee2dbb563a3fa026b26aa374ca2b3baf53df4d8e3895af5990f7d40abb5d9085c4e9cbafb26b4c575f6ce908ca7597e1a03e10f161ced3a4e1e9028328efac38d893960b36c7a7de09f970b098ea37710878d6467f2d649067ac263ec249f7bd8b8ed51e4fe44bdcd390de9d657c176120f603f9610e990e8bb3a8a12172124a4a06014c9823b95dbb6c2d29633e01428d8c6050b357dff2d37afdf49cc717665621bc91c77fd3074daa3e086dfdd159476fcc03a07c18f325ea0bedafc038af9efc346ea859196438cf9e5f2a944664483e096dec37bfc6537c72d4415439e721e9714e07ff5efc3c4ed8be1903464fa4540a7ccbcad2e3da1ffc4fdb54f7f810371995c16cc8e7722b03bff16ad3e9a7c82b0f9ca2d83ea81543a46e169bb7583cdf5938e85c8d7566824ebd8041ae7063538ee973d37e3da7315bb7d33eb9b9877af3e7f35999ce91a6fbbf28d31bdb05cc478326961913f3473fc2c3838848befabe769ec5046ea3dbf6a4e58a197541f1eabca0337173dca38085505b53607625467cc138ee58cd92559637d71e62a264ccfc97332f549f12d80347740eee5e9daf06867393d25ac370419fb40d8723fbb9c4f55147fad61d935f0e937b4f38d4896c2195fd097b0845077f74b098cde29037ea7e92e28be175bffd399d8563108a9005c219a88b1c366936654da39849e9169a3269ae0ffd80d74757e3b8b7f0b85c48470920dd4323a5dce5d2ea484e9220b5ea3c2993d48a9fcef4991a47d50fbb75628a9de22271301d726c8d47857e9cb2a040c329863809b0b3f0bbf8f891516826aa763616650005d361ed51148fa212369140988c3aa01cb16f211c96bbb75bd2981ce7cc081efef0eadf56a0e4e047dea1a07a762a1375bdc4704b30f18c2ec044123c1b3754084da3ff62d90ee61b4cc453151e2072b46264f385ae1b485f1573c27b800e3804f06c9dd7595dfd1423c4fe0cf0bca2a2eb570a78c66985efc3d2113e9cc28ae6f94247bcc2c6e7d4c18752ec7a9532da166d50329d8bbc1c798196c30d9825fae53fad34d4e7f20d1ef3cba84376b56f5a063cd91fa9f17a059b452e028c68ad14990e15466e2dfa0034bf3c6162e9cf5ae88c72be95e789f9a12ec545c4010cdfc8bca57c9ac927b729af2fd7ec1e11f3b693cdf7b734df393283aa19d815416e77259fab3269505a322814da13c7055e12d6bfaa1ad29a17d94039bd167cbf04cb49d8b6d799e192c65a4d25fe223e550da47e8af95ae2f3250502cf17249c3c3c1455542a95faed7bf9fc71b1b077957c9aea1eee229b5c4012dc23aee8ee6b6008b9c416120f72d48ac8e79837ea21adc5cea6e43112ce3910f80097130cb8ee076a06d800e4c2ae73ca8904549046f595a9f1471eb54c89b1a0850292978fd9eab9056feb945b5cc04c8534d94c3a5a331f7dedd096aa6b211fed44105fd7409d05e729040b9f67d88579046ad1a36e9314aed9c91faf9755abb2bf2b8df9ff0553e41433bcc5f3d724d50fb60dc7f712e765d497296fa5edb0b432563afa4621e2863a57bb8f772d3284d9a985b0c650fcb60617fb93117d15a1209ced94d031094195fa94ab32d66a2c750e14273e6a62c93e4bd7a06670ce4fc819a08246a788c47ba379108c05d26e60113b9f0f9440a531a4ba6cfc3c9b8564bf8bd1f4e3cd00e2c19f8f935e2a921bfab0c15e49a172a28e2ddae40b30a0caefe475174b245aa27ca162e50a8cd2d7fdf5dedca0d2d812ddd50950250aaf9a4475d9ae9b9c85970305e3959ceef8f9b131b22d4c1e291b39e82d5acbc0e63569a15187cada04d43f9a2c194285e2d992c0de5ad6fa01d726f8e1b684de19b2409b5f9f028d6f915afff0b5f2a40f0ebc3ede023058575ffb33dc5be1ed2b4e477f566345246f59596738c2c082c53ffb59bd3a9c684f2e5a465a7cd8827a54de7f17631d57d41c62833a796649e61188b217265eeebbeb5c2d86d27f52924d708515bf00aa4a6c42429f7d7949faff15eb23c75ed8525f812be080afff85c113437e94cb346cbdef8b8a008982659334e04a64e471fb9ee779f5f9a4904ba7bdeb9468764b3afd6539c5d6604cf6ad6846367e6f36623d75bc0b1316b92c36c284d8f80113e60c7ff1e87f2fec0fc64a354f5b53a01acac64304794d393ccd2c8c652ad13f0937a1123572ca3538a1a36cb470a73c533d4c519c139cc1ee49d0c7b43af7514ceab5ee0a1d14b1ffc03bfcf53b8aeb9eac66ef62ef14d002a78b1242e40ffa6d3600678ecb5f61380f0c67a6dc4fbc2f91381b75c60fb7e17d78e91957df3ce1dcba5e248ad980a70d3ca691f203acaa82d14f97e0a53c0ed1b1719a9aa63cbe1b4f9c8d60022909fb57ccc46d3ca95f845884ca5f5e6c9310f7d112b9e327ed5c164b2234b5e97c75cd48e9d224818948feb0409cef961da614fab0a41a258b5d96a12209eaa06522e2936bd44b6686b4e119f7a1895615578144b42beaecd9710e9853a97d007aacaeebf634959120813da8a5c5400d2963475a685a14522f63873cf4e3ad2e288364c66633de090061b41e153c9b405f91d659382e58b893d376f9624a0871e741fef0e3df6f77b76a89f9787a2fb5add0a8a858e45e0451f59f8db21ad581d8fc738f6b50f206723b83c5f0c40e1d9aa1fcee985ac7c45aad19d7c7fdf2313039928c44d19a02f78c1d28456fbb39fcf0837e188829ac002b7bef7526975e8c81fe01787ef964fe19bfab61fbcf850607c8f98525653b94cb5d7ea8233d294a59b249ef5e0225f086a1ae89ea35085bd5e3098e428c1ebf99785bf1f24c9d16b6f4fc87b06c8e133103fcc3dc90e5c311bfa05bd357669f2190f08ed18489949e7e36ca8d4d329c9df52f1bd45f8f1d2c0e899a165887129e7ecd9dc4e51a5e4c43e148cb1f684fe8a183a2752cf8101afb5819eaf93a0afff8b8302786df1213634cad9acbaf0704a479c2db26b5f7febd1cb426fcffe9881ff235fbab9ecce592140c947507b55b57270841c962375b89e90ad91263b112a7880118e6db8d5d8765beaca0ef37594ff49fee717c9f3a40b12e7977b5d15643cd0b3f35d37833d969bc45a16cf04153ce949105b3c58fff68b3d67d9c8e2060486c8f944630a2e48b2b55dc00d38f17fc5e7b6f46db34a13c3b83a3a37846db3a52654b9dcbdd6da8d2a4c3300c7a63198a255820b3cb059842caf85e500630f00c820d92a35f1a1fd4433b162b80fbc273ae34a4b2b457da1a50dab1e4ccaa2244944787bae5b385a7a81b3fb2af4fb1015ea0484e1a220722f00a9fbf2797ec4daedea2d00a5e6a77201c572d3bcb47f82b89c17790d10726ab55d2d7a407f8c7db2a2874a5a76696b118318320fc98603b46f5b5e11000fcb068c11f6b402eef2d209af6e3071a46b69684df524c5e68091e117494cfd180fd975267a5d82b388995da1cfc2bf528b54060e36d7163db7750a9afcabc24269796ee60534b4d960eb9f9459bcb89a9d516d7bbdfa0212ec8cc4080c661cb9203b24052221e97c65fc7d1b4baba020a5e4ebfa8072e03530e46f7e78abb2a1ff0578f6128da33e85fcdb2c19d5e601f8c77a65cfc401a67bf888f375396e31d32c5674d97ca30feb543bf66d5fc1fd08bc2f9fa9fdfd6a0477f8a9973b672a3aa72652fee2496c895c58a0ba02edf952b5feae24387fcb5ca73d1";
|
|
BB := "2937beb399926019948796c29595aa37cfbddc2ccdd8fb9ae367f45943210393e7e0e5bcbda767fef76d3691d26708fa8e10452ce5d4fc98bd19c0104100a12cd992864e875d3d521cd3d9713dbd5db86b2a94faa7ec7ea92e761967fb89ab9a0ea2561d4c42f747d1d52d3ca3d63359b4d7ebc2db1841546df87f99078232928bee89c028cd92444022811a81ec6c95e168b6c2e94a37f3a59bb5891d6e7e6a85b57addc4aae712e527a5a2735b11513929d67471ca5104508e219610e1fd2c363b98a3b6786d5b84c6e57eabed5a4e91f4b4ae24edf57afb792f85090eb0985bb1c53e3b0efe41f0c78a82aa150d2bca685cb30bbb2aef495afe455135c378d48f8fe360670d2e9e186fd3c55eee0f9dc23a9cbaf4dc887a6e3765850b8d95360ea3ebc72ec57382331f0339a57ddc82a97350bc4d1351debd63c38b0b1240d7a8e0fd75a302a40ddda27a8c6dbb18d5e76fef1118807bc5b5f9a19d96e789cc0e26da0987fdbee7ab544f1f742b741bc5d4640496e562dfbf198fd8a2c5d8fd8b6a22cdabea362b1cead3d0eba56ae8462b30c2c9b40612722c3887fda1ab8ed8c5b1439b0a8bea536bc9b2dbdab2dc91f20bd1a71709e19f2f7f7b70cfbc0a9fb1d12b1fabc3787abd687e1c2573b2340dff3660c7b6abfeb082b852b4b4cc5aee178392693a4ca829c8b5bddbe57b972c357c268d3eaed55e0c6e913aefece764b03e015cf150ab3815c9b6ec51df0a9a95c32155f3044007c35e64a47292364a96b998c044467fbe63e5628d3b1f21c57ecc32578dd50ad926376a916c8378d1f33e0e9bcb3caae70c08c44aab747920eb2f7a84eb1842ab8453d0488aec38a5a62b711f9895a8089465275820679bcba2d3c0b71a0d17f13a46ee630f56a987683032562919a750df84395294c34737a34d9c3f87f73f68d0d73d6eb4d7683bddf901100db696b38a677987f746d09ca5a59988df9a3423604e4a892501b4669bdcab7304a374194099fa4a43ce381d21240aaa08b6c29a8a3b94725051a4ac430bcf3f1d6238e33a59a83789cf5d68aa5f001a72bb15b3a08925081af9105b01c2233bde416dbeda5ff88e14f164cf1d6bde98624da2be67f8e1166dd7f9982a3a525b7bcc95b8d7a3635e84e2e080b59694d89ce5f8e4329560586f31a9d7922b9bec0efe2843a7a0780f0e7482dfe432edc0cc2470f1f9f95cf833fe7678ba06e92eefba64675a5da590898c95568a934295ebd04ff73382c7ab24661eacb98d32a6e194101d127dbc92e5a83aa39e5a6e5fa3af10521f148b9f53308b019cbbb379c0de0a82042dc5d2c016c716cc305c3c602c2aea99cc50d26d480376630616d06687f329b0ea0106f02381ef74efae778e71a9ec87a6c195a06c08268ac0739bcdf05bc1a233aa9878b110e1903eff8a53a54cede923d98d1fa75f1e69c19f414486645b96932cfb8145b344ad243038c1c42a348695a2831cbd6585fd31189a24fa615b19e226f4ea143d00b4bbd8e56e4fa7eb5f09270f1283a4b808fa7d3ee3da7eedc3bd6cf15303a15bc1240b0c07c0e34b88c563463ec9c64ee11a887d3e8bc1a0c2cc3680f19fe534a41fe1cf822599e8e6ab128e17f3bae77fbbc746298d8f3677afba82d1ef7e978d785a2d84f96c3fbe00011542e07a9062076233116c662430520bcef5bdb5cc9139b1f01f32d57e9ddcfd27e98a630b5f9e980172370fc4d064649fff411a2d913e75aef9101edb709ce091d6e973b033de3787c504967eccec22bc37ec43afb01f50a655040f14b2832c895990e81c94d546f3a350b8a109eeeddc714ea6c4de00e9102b8d1eb69e3b4c2ab28006d144baaf78ea13ca1bbad46bad5d3bcea7f8c99645fb33cbc554c053a75a2a2014fac095975a2215cc40472a6f5d6de6618e6eb05eb8b97ee1aab6425219bc6249f0f327fb6f33879ba1d4e3feffa67ac26aa857dd924f4f91cb76bd724b70a0a3dbf57b94484f678c2e2582ae69f3d219a0e2fa5f3cd1124cc0b2cb7ba928921277989d4e416ca617f53e5e9e215d5472526915d822bfefacc6d6102aa4b53655aad0eb7690d2f795b16fe45715aaf5825b7cda38b8c12f234538318e042c48542ac18456a37a6988d3e030bbbfe634c7df9dd50bf526b9762e86ddbf5fadc0a7be4a5a929006fd71bbe353e6054976146df7c713e1239f5c79d23ac33a1ace757d8a65a909fdc79791ce9d13ecd17e7533a7deb8928749b07b7a3e07c2684e01081da33337d8f6fc477cc36ff46063626370b747c72acf11510f911c8d8623c7dd4d96243e4e5088657f49fbedf3300b07bcc4334e7197dce79b79241c42fa12007817e80b2b8cd2c8e802372ad1f167400ac69bc2fc8a58bb689dcc66dd642d0dfd0f2f84c372157563fac3a98fcdd1acc7b569d8da11c95e5d94cac5c5d01b0333ca2171af2b12a341e71e4d2ab721b54ac981d9c69cfee5691c2f7177e4a3cef997d98b01fe3eac117f671c0e92b810070400bec1f24a283c2da70fb9b505aa22463c90736017dd670e60ae711d1158fe2e571621d35e5004657ef29eab35c716dda196d7715a6a933f8e4e52e43fe154f685540bae72c23befef55f1b72ba4f8634e09a66184f4ffedc5d72e60f1843200cb178e05bd1ee01d9637adcedc2dbd98a9100ff807dfdfa0ba7595ae27562476f17eec6c70a5438ada39ac0fdcf882a212cac3ebabfda6f478c3d834bac8c8e458c7fbfb212f19245869b5258f3e5149cc0559ae57d24f78fa31dbb613b9e1d986187ea3dc876139d8fe08ad823d0ff55d3bddefd91929432147563d9c410197d536e2bc925157439921eb6ca8e3cc8c7717b5a2852b980d8e1e6db7ed88f7b3a920ff9b8022aa4b190b32aaab2b84813ed49a06d3f253abefd9710de64ffdf56d9dea2c040ed850a5e59e542059bdfb9a41044fc5e9866cdba0f62a52535f7db238f4635b00be08d9ee6e3f37d9d28bdc3f2e07bc5d6299e04181cb811e7d05fa2b9c49f43b764161a73f3a61901f5a934802e3e1a58dad63711e986334762d38ee2cdaf5540e4af66ac60df2e74ef922a687c730e0e5ef4e9a683918d41feba17f53bbae933ac9e7ac7f69069f8d23af32d3f0f54771febbfb70efe0ff7076258b4d5f90c12da20f3969b140b1367f3d09d3e934c43641a423b73773a1d6ab32bdb32003433db68fa35498bdd33b450dc88e44c955355e1c219dfd9324180dcdca07455dc43a6da573f9fa5028d3f9459e3a6e10b0de3014b8936c081c1b620293ab9760e7ff3019ab263d8df1a149e64088abb0b4c96d6f7188231afc37b1348fd55127d612e4cfbc01453fc38bf2db85b1f13884352e860d28e98d55762e87eb1ed4fd3f9be45c3f2f9d465d094e4ade75c2e3a88f555414c68eadff600aa0dbaac9c9e85755dfcb8ade4e713ac45a2733d5a78ca96b4338b65fc43503dd8189b9ecc8622e3ac01dbc761c3b24e9769dff069799f1b65e80cac2b19213bb52c6a1b1c04fe06f3651b86d7d079b4fb0c3f49ec58d41c085bb7f46986395a9502a4c791b66ccad5ca53e9e117236b817e9f2f7ed0bbfe4fb9720f2602486a0819815fe4779637c68806ad128cf965458704b9aca4a5bb3ab11081bdda290f833cb3e78ffe9963bfac4e65841bbe46ef99c336bb7b5b998f551f71f2996892bf85466d0097bc968e2d25fb7615e3287c8296671aaf1921caf8ab142e66e3f85659da770aaa6d56a7a9bd6f26d577c9ad8320ee3d6f57ec900d71c2e1ac1b22b03023f4e5513c03d617040f1dfe42c82b086f0042b05a802e5e3c068542b38d9e7aa44618e01725dee4acd87ec16cd6a76816a4b98a29cf25c70c093e75bd3f1a907ea1f20b8d60de492644280a37b6443f7340a0d8a9c482eb8f34dbcd121479685dd3d52c972d67bfcd79e20705b6160ff5a2834d68c8b7452da582751b1b30a8fa26baf966b80c0ba933df75b87c1d485959a10691794d0ef11067538a0968fcdc1c5d82a07196f6fb429060238095f5af1bd5440c6b4312029de3d12e917c61b3df70be76a7d1965aedd7d500ddc52a3a0c9abc1aafb5d250d804f310d1818e49fa38a182b9a5da5d77c552da65478dfd51fee24543e509f1f6988de3ec6a0772d50433caea33c4a130f9f26ba3b707464a645ec56125c037fa4c94ca55f19822442e6334ec57c51bbeb17ae8ce0d7a0a3202c2cca77ca3f919f3f0b3966a8abb0c9b5d635956e2534c03026fb1c71c8574ed37d6effb1bdaf3f79fc335839113008e1fea16dd33091e70d62798517fe0ddec0232433f4a362c3a1196f0cff3bd457a0e54dce5aecf740ffc64558cde2661332c57a784b53cdb863499d4130b14e0cfbaa8ecc3490ac3a7efabcce2a62b19cdf30132763e3623fc02bf81118720320e0c9c8ec57320d940d58c523034d54af5128dd311862a1e4efcb4e434fa9eb169ea9a1bea6e20b0aabc99a3b93d5a928bdca9e64f4dd60e8944ccd5235fafbeaf737a6ac1377f5bf62105c1dda61b6c783d930f670cf619eca135f08ecb73fb0c27cb6e0536f443f7eadeb161b63c594a0deb7ea5eb29a4ba35e38b7a3105e64f9fad4fcda643bb96e6392e2364afa00602c279f0bc7969e9e41c50d7d4d4c25af7c2e6ccd110078a1ffc7d690864d47b93d4823863b2e4584d1e2a8183d7e3167082b2a7f457aefeef2bf03dc9e7465d3e0e2f2ad4c0d9c601b5820f15b76f7865d4247124db078ba10d3bca492e18d08dee32394dc2c280ee22fd39faab4297c1c5c17dca8a7a399dd6d2546f9386fd381cc7a0feedde600cc28dd88628e4a142174df66381345cc6a01dd7a7dd4deb664c1407e950edb3671edf19094cdf76edea414339ee1b73abf0be2bd41958b5c5899affaec6a0fc1b6934a062ff921844211ff5ecde5f4e83ec6b9eada5b060936a0d242447692b540f52bc357aabf519d35be48f2378bfb4049f75705469f86dba1200381631ef8925451533268adebbf45514ad8c1023748bfb7f2fd4466e6200bfdc86acc002bcf9cf3dd7a26e5f04ae03ddf29b592073eb1748dfffa58fdfe083c222c077a50087d208ea7e7899d086202e32411302e55ef7adbe0d4a3d2fa83a6ddb4d6a36440953354151ac09c39fb97bcea516f7630b10e20523dab7b46ae8259994871364bbf851e376271fa2549c56ea1e01dd0d0ff470dc07957d75be88cf0246c259fb2b81b795eae95b9cf5ddcfa7e76894eec44ea972c0a1b01f510eb3b8efcf38b276b25ae559382dbb361bac346ec013be81aeda65373b31bf45e40a06eaf32ddf26e6a93a35b18292c5f88b817faf99183ed1a568b3915436ec334c61eb1d1a3884699d80051ae928517905a6e91cde31e2a9d1d8a12b3d2ccca187107babe7855e3ce55d1a76b09ff3e0cfca59438238635184fe145eda16327732c7d3be18491efc192b9107bcb054115939cd7bc8952aef58a9a729f79e629e69ebbe7d4900a0b2768b70eb9cd2e93e4a47af2aa45efd81a247d9b99d21856f875fdba0226e37afb7a10bb08dcd0aa8a68d42f8163f132d2899d47ae673ccb8d63ee2257d7c80d89e009d5198e19d3e00b3ff89f57affce3220a946cf01725637ae0cce8a2dc6d73ca49e57e3b2a2c22f4761dd4341632b923a650ab098232e2319c0765197d09c09df469d944758f287a8988d83e7cd39f7c945a1491d84aeb6fa133607f8f0a32e201b4aa993403f2846067bedb158dc5e8d6c244cbe3ff0a7fb1e20f722c933da2298fec98ef691447aed631bc829c1792016a0069392820ef6a2bf22338b5273a0fcd0cfa5a6ffa9cf83abd327f0313fa78b149cbfb89d2d8415ece8916719b35eb77ae3d708a6bbb7722e0deabba2c2903e22d1366238ae54d0d1cd4934c7bb3016faaf2ec03aa9a1d5bd79dcaf20631d1a4710e7031dce66e9f2c5635b53c6ccb8b2b404b93f9e7ff45a6b3e3ccc916a0fd666626a65cafe72af5aa8e4cef";
|
|
|
|
demo :: proc() {
|
|
a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
|
defer destroy(a, b, c, d, e, f);
|
|
|
|
atoi(a, AA, 16);
|
|
atoi(b, BB, 16);
|
|
|
|
_private_int_mul(c, a, b, a.used + b.used + 1);
|
|
_private_int_mul_toom(d, a, b);
|
|
// _private_int_mul_karatsuba(e, a, b);
|
|
|
|
fmt.println();
|
|
|
|
if internal_cmp_mag(c, d) == 0 {
|
|
fmt.println("Toom is correct.");
|
|
} else {
|
|
fmt.println("Toom is not correct.");
|
|
}
|
|
|
|
atoi(e, FAC_6_102, 16);
|
|
factorial(f, 6_102);
|
|
|
|
if internal_cmp_mag(e, f) == 0 {
|
|
fmt.println("factorial(6_102) is correct.");
|
|
} else {
|
|
fmt.println("factorial(6_102) is not correct.");
|
|
}
|
|
}
|
|
|
|
main :: proc() {
|
|
ta := mem.Tracking_Allocator{};
|
|
mem.tracking_allocator_init(&ta, context.allocator);
|
|
context.allocator = mem.tracking_allocator(&ta);
|
|
|
|
demo();
|
|
|
|
print_configation();
|
|
|
|
print_timings();
|
|
|
|
if len(ta.allocation_map) > 0 {
|
|
for _, v in ta.allocation_map {
|
|
fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location);
|
|
}
|
|
}
|
|
if len(ta.bad_free_array) > 0 {
|
|
fmt.println("Bad frees:");
|
|
for v in ta.bad_free_array {
|
|
fmt.println(v);
|
|
}
|
|
}
|
|
} |