diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln index d921262b0e..67f018180c 100644 --- a/WindowsAppRuntime.sln +++ b/WindowsAppRuntime.sln @@ -685,6 +685,51 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StoragePickers", "dev\Inter EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StoragePickersTests", "test\StoragePickersTests\StoragePickersTests.vcxproj", "{85C86306-46D1-4563-8303-0A79DF923586}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Decimal", "Decimal", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Decimal", "Decimal", "{5012149E-F09F-4F18-A03C-FFE597203821}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Windows.Foundation.Projection", "dev\Projections\CS\Microsoft.Windows.Foundation\Microsoft.Windows.Foundation.Projection.csproj", "{8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CPP", "CPP", "{7C0F3E70-BDB3-40B2-84E1-B1B77A80CB53}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CS", "CS", "{AB515C38-1A93-40FE-917B-1998DCEB811C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DecimalTests", "test\Decimal\CPP\DecimalTests.vcxproj", "{4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}" + ProjectSection(ProjectDependencies) = postProject + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DecimalTest_CS", "test\Decimal\CS\DecimalTest_CS.csproj", "{041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}" + ProjectSection(ProjectDependencies) = postProject + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA} = {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {D6574FD6-8D13-4412-9FCB-308D44063CDA} = {D6574FD6-8D13-4412-9FCB-308D44063CDA} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DecimalCalculator", "DecimalCalculator", "{A7A0250E-A0B6-4499-9A41-8EFDCC1D9FD3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CPP", "CPP", "{F4F96552-D5B3-4075-A335-ACE45CA6369D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CS", "CS", "{6FE937DC-8AEE-4191-B6BA-51A32DE27ABE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DecimalCalculator_CS", "test\Decimal\DecimalCalcuator\CS\DecimalCalculator_CS.csproj", "{5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinRT", "WinRT", "{022E355A-AB24-48EE-9CC0-965BEFDF5E8C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DecimalTest_WinRT", "test\Decimal\WinRT\DecimalTest_WinRT.vcxproj", "{E9C055BB-6AE4-497A-A354-D07841E68976}" + ProjectSection(ProjectDependencies) = postProject + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA} = {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {D6574FD6-8D13-4412-9FCB-308D44063CDA} = {D6574FD6-8D13-4412-9FCB-308D44063CDA} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Decimal", "dev\Decimal\Decimal.vcxitems", "{DC453DE3-18FD-43E7-8103-20763C8B97C8}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ABForwardTests", "test\ABForward\ABForward.vcxproj", "{C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99}" EndProject Global @@ -2389,6 +2434,86 @@ Global {85C86306-46D1-4563-8303-0A79DF923586}.Release|x64.Build.0 = Release|x64 {85C86306-46D1-4563-8303-0A79DF923586}.Release|x86.ActiveCfg = Release|Win32 {85C86306-46D1-4563-8303-0A79DF923586}.Release|x86.Build.0 = Release|Win32 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|Any CPU.ActiveCfg = Debug|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|Any CPU.Build.0 = Debug|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|ARM64.ActiveCfg = Debug|arm64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|ARM64.Build.0 = Debug|arm64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|x64.ActiveCfg = Debug|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|x64.Build.0 = Debug|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|x86.ActiveCfg = Debug|x86 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Debug|x86.Build.0 = Debug|x86 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|Any CPU.ActiveCfg = Release|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|Any CPU.Build.0 = Release|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|ARM64.ActiveCfg = Release|arm64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|ARM64.Build.0 = Release|arm64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|x64.ActiveCfg = Release|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|x64.Build.0 = Release|x64 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|x86.ActiveCfg = Release|x86 + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}.Release|x86.Build.0 = Release|x86 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|Any CPU.Build.0 = Debug|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|ARM64.Build.0 = Debug|ARM64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|x64.ActiveCfg = Debug|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|x64.Build.0 = Debug|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|x86.ActiveCfg = Debug|Win32 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Debug|x86.Build.0 = Debug|Win32 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|Any CPU.ActiveCfg = Release|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|Any CPU.Build.0 = Release|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|ARM64.ActiveCfg = Release|ARM64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|ARM64.Build.0 = Release|ARM64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|x64.ActiveCfg = Release|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|x64.Build.0 = Release|x64 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|x86.ActiveCfg = Release|Win32 + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA}.Release|x86.Build.0 = Release|Win32 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|Any CPU.ActiveCfg = Debug|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|Any CPU.Build.0 = Debug|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|ARM64.ActiveCfg = Debug|arm64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|ARM64.Build.0 = Debug|arm64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|x64.ActiveCfg = Debug|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|x64.Build.0 = Debug|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|x86.ActiveCfg = Debug|x86 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Debug|x86.Build.0 = Debug|x86 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|Any CPU.ActiveCfg = Release|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|Any CPU.Build.0 = Release|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|ARM64.ActiveCfg = Release|arm64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|ARM64.Build.0 = Release|arm64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|x64.ActiveCfg = Release|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|x64.Build.0 = Release|x64 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|x86.ActiveCfg = Release|x86 + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5}.Release|x86.Build.0 = Release|x86 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|Any CPU.ActiveCfg = Debug|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|Any CPU.Build.0 = Debug|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|ARM64.ActiveCfg = Debug|arm64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|ARM64.Build.0 = Debug|arm64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|x64.ActiveCfg = Debug|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|x64.Build.0 = Debug|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|x86.ActiveCfg = Debug|x86 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Debug|x86.Build.0 = Debug|x86 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|Any CPU.ActiveCfg = Release|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|Any CPU.Build.0 = Release|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|ARM64.ActiveCfg = Release|arm64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|ARM64.Build.0 = Release|arm64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|x64.ActiveCfg = Release|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|x64.Build.0 = Release|x64 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|x86.ActiveCfg = Release|x86 + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646}.Release|x86.Build.0 = Release|x86 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|Any CPU.ActiveCfg = Debug|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|Any CPU.Build.0 = Debug|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|ARM64.Build.0 = Debug|ARM64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|x64.ActiveCfg = Debug|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|x64.Build.0 = Debug|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|x86.ActiveCfg = Debug|Win32 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Debug|x86.Build.0 = Debug|Win32 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|Any CPU.ActiveCfg = Release|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|Any CPU.Build.0 = Release|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|ARM64.ActiveCfg = Release|ARM64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|ARM64.Build.0 = Release|ARM64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|x64.ActiveCfg = Release|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|x64.Build.0 = Release|x64 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|x86.ActiveCfg = Release|Win32 + {E9C055BB-6AE4-497A-A354-D07841E68976}.Release|x86.Build.0 = Release|Win32 {C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99}.Debug|Any CPU.ActiveCfg = Debug|x64 {C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99}.Debug|Any CPU.Build.0 = Debug|x64 {C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -2613,6 +2738,20 @@ Global {8E01AA4F-A16A-4E3F-A59F-6D49422B4410} = {716C26A0-E6B0-4981-8412-D14A4D410531} {A39E7B2F-5F67-47DD-8443-531D095CA7F3} = {3B706C5C-55E0-4B76-BF59-89E20FE46795} {85C86306-46D1-4563-8303-0A79DF923586} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} + {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} + {5012149E-F09F-4F18-A03C-FFE597203821} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA} = {716C26A0-E6B0-4981-8412-D14A4D410531} + {7C0F3E70-BDB3-40B2-84E1-B1B77A80CB53} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {AB515C38-1A93-40FE-917B-1998DCEB811C} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {4CBAF81E-F2F2-437C-BE4B-8F457DA572AA} = {7C0F3E70-BDB3-40B2-84E1-B1B77A80CB53} + {041C3EC8-85CC-83C3-9815-0B10CBD0E1E5} = {AB515C38-1A93-40FE-917B-1998DCEB811C} + {A7A0250E-A0B6-4499-9A41-8EFDCC1D9FD3} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {F4F96552-D5B3-4075-A335-ACE45CA6369D} = {A7A0250E-A0B6-4499-9A41-8EFDCC1D9FD3} + {6FE937DC-8AEE-4191-B6BA-51A32DE27ABE} = {A7A0250E-A0B6-4499-9A41-8EFDCC1D9FD3} + {5B07A0BE-62CD-C63A-5B0C-5CA48A98A646} = {6FE937DC-8AEE-4191-B6BA-51A32DE27ABE} + {022E355A-AB24-48EE-9CC0-965BEFDF5E8C} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {E9C055BB-6AE4-497A-A354-D07841E68976} = {022E355A-AB24-48EE-9CC0-965BEFDF5E8C} + {DC453DE3-18FD-43E7-8103-20763C8B97C8} = {5012149E-F09F-4F18-A03C-FFE597203821} {C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution @@ -2646,6 +2785,7 @@ Global dev\ApplicationData\ApplicationData.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\BackgroundTask\BackgroundTaskBuilder\BackgroundTaskBuilder.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\Common\Common.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 + dev\Decimal\Decimal.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\DynamicDependency\API\DynamicDependency.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\Licensing\Licensing.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\PackageManager\API\PackageManager.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 @@ -2659,6 +2799,7 @@ Global dev\AccessControl\AccessControl.vcxitems*{c91bcb93-9ed1-4acd-85f3-26f9f6ac52e3}*SharedItemsImports = 9 test\inc\inc.vcxitems*{d5667df6-a151-4081-abc7-b93e8e5604ce}*SharedItemsImports = 4 dev\Deployment\Deployment.vcxitems*{db38fb4d-d04f-4c1d-93e0-f8ae259c5fd6}*SharedItemsImports = 9 + dev\Decimal\Decimal.vcxitems*{dc453de3-18fd-43e7-8103-20763c8b97c8}*SharedItemsImports = 9 dev\EnvironmentManager\ChangeTracker\ChangeTracker.vcxitems*{e15c3465-9d45-495d-92ce-b91ef45e8623}*SharedItemsImports = 9 dev\AppLifecycle\AppLifecycle.vcxitems*{e3a522a3-6635-4a42-bded-1af46a15f63c}*SharedItemsImports = 9 dev\VersionInfo\VersionInfo.vcxitems*{e3edec7f-a24e-4766-bb1d-6bdfba157c51}*SharedItemsImports = 9 diff --git a/dev/AppLifecycle/ExtensionContract.h b/dev/AppLifecycle/ExtensionContract.h index a7a2cfb6ae..b60bf5bc30 100644 --- a/dev/AppLifecycle/ExtensionContract.h +++ b/dev/AppLifecycle/ExtensionContract.h @@ -55,7 +55,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation // QueryParsed() function would return empty when it's a file contract with unicode characters in file path // Thus following additional check for file contract is needed auto fileContractUri = GenerateEncodedLaunchUri(L"App", c_fileContractId); - if (CompareStringOrdinal(uri.AbsoluteUri().c_str(), fileContractUri.length(), fileContractUri.c_str(), -1, TRUE) == CSTR_EQUAL) + if (CompareStringOrdinal(uri.AbsoluteUri().c_str(), static_cast(fileContractUri.length()), fileContractUri.c_str(), -1, TRUE) == CSTR_EQUAL) { return { ExtendedActivationKind::File, FileActivatedEventArgs::Deserialize(uri) }; } diff --git a/dev/Common/TerminalVelocityFeatures-Decimal.h b/dev/Common/TerminalVelocityFeatures-Decimal.h new file mode 100644 index 0000000000..097136943a --- /dev/null +++ b/dev/Common/TerminalVelocityFeatures-Decimal.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT IT + +// INPUT FILE: dev\common\TerminalVelocityFeatures-Decimal.xml +// OPTIONS: -Channel Experimental -Language C++ -Namespace Microsoft.Windows.Foundation -Path dev\common\TerminalVelocityFeatures-Decimal.xml -Output dev\common\TerminalVelocityFeatures-Decimal.h + +#if defined(__midlrt) +namespace features +{ + feature_name Feature_Decimal = { DisabledByDefault, FALSE }; +} +#endif // defined(__midlrt) + +// Feature constants +#define WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_FOUNDATION_FEATURE_DECIMAL_ENABLED 1 + +#if defined(__cplusplus) + +namespace Microsoft::Windows::Foundation +{ + +__pragma(detect_mismatch("ODR_violation_WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_FOUNDATION_FEATURE_DECIMAL_ENABLED_mismatch", "AlwaysEnabled")) +struct Feature_Decimal +{ + static constexpr bool IsEnabled() { return WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_FOUNDATION_FEATURE_DECIMAL_ENABLED == 1; } +}; + +} // namespace Microsoft.Windows.Foundation + +#endif // defined(__cplusplus) diff --git a/dev/Common/TerminalVelocityFeatures-Decimal.xml b/dev/Common/TerminalVelocityFeatures-Decimal.xml new file mode 100644 index 0000000000..a70b9ba6d6 --- /dev/null +++ b/dev/Common/TerminalVelocityFeatures-Decimal.xml @@ -0,0 +1,20 @@ + + + + + + + + + + Feature_Decimal + Decimal APIs + AlwaysEnabled + + Preview + Stable + + + diff --git a/dev/Decimal/Decimal.idl b/dev/Decimal/Decimal.idl new file mode 100644 index 0000000000..f0e44b3f02 --- /dev/null +++ b/dev/Decimal/Decimal.idl @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include + +namespace Microsoft.Windows.Foundation +{ + [contractversion(1)] + apicontract DecimalContract{}; + + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + struct DecimalValue + { + UInt16 Reserved; + UInt8 Scale; // Allowed values: 0-28 + UInt8 Sign; // Allowed values: 0x80 = negative, 0x00 = zero or positive + UInt32 Hi32; + UInt64 Lo64; + }; + + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + runtimeclass Decimal : Windows.Foundation.IStringable + { + Decimal(); + + static Decimal CreateFromBoolean(Boolean value); + static Decimal CreateFromInt16(Int16 value); + static Decimal CreateFromInt32(Int32 value); + static Decimal CreateFromInt64(Int64 value); + static Decimal CreateFromUInt8(UInt8 value); + static Decimal CreateFromUInt16(UInt16 value); + static Decimal CreateFromUInt32(UInt32 value); + static Decimal CreateFromUInt64(UInt64 value); + static Decimal CreateFromSingle(Single value); + static Decimal CreateFromDouble(Double value); + static Decimal CreateFromString(String value); // LCID=LOCALE_INVARIANT + static Decimal CreateFromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() + static Decimal CreateFromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() + static Decimal CreateFromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + static Decimal CreateFromStringWithInvariantLocale(String value); // LCID=LOCALE_INVARIANT + static Decimal Create(IInspectable value); + static Decimal CreateFromDecimal(Decimal value); + static Decimal CreateFromDecimalValue(DecimalValue value); + + void SetFromBoolean(Boolean value); + void SetFromInt16(Int16 value); + void SetFromInt32(Int32 value); + void SetFromInt64(Int64 value); + void SetFromUInt8(UInt8 value); + void SetFromUInt16(UInt16 value); + void SetFromUInt32(UInt32 value); + void SetFromUInt64(UInt64 value); + void SetFromSingle(Single value); + void SetFromDouble(Double value); + void SetFromString(String value); // LCID=LOCALE_INVARIANT + void SetFromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() + void SetFromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() + void SetFromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + void SetFromStringWithInvariantLocale(String value); // LCID=LOCALE_INVARIANT + void Set(IInspectable value); + void SetFromDecimal(Decimal value); + void SetFromDecimalValue(DecimalValue value); + + Boolean ToBoolean(); + Int16 ToInt16(); + Int32 ToInt32(); + Int64 ToInt64(); + UInt8 ToUInt8(); + UInt16 ToUInt16(); + UInt32 ToUInt32(); + UInt64 ToUInt64(); + Single ToSingle(); + Double ToDouble(); + //String ToString(); inherited from IStringable // LCID=LOCALE_INVARIANT + String ToStringWithSystemDefaultLocale(); // LCID=GetSystemDefaultLCID() + String ToStringWithUserDefaultLocale(); // LCID=GetUserDefaultLCID() + String ToStringWithThreadLocale(); // LCID=GetThreadLocale() + String ToStringWithInvariantLocale(); // LCID=LOCALE_INVARIANT + IInspectable ToObject(); + Decimal ToDecimal(); //TODO: Rename to Copy(value) or Clone(value) ? + DecimalValue ToDecimalValue(); + + /// Return true if (this == value). + Boolean Equals(Decimal value); + + /// Compare this decimal with value. + /// @return 0 if this and value are equal, <0 if this is less than value or >0 if this is greater than value. + Int32 Compare(Decimal value); + + /// Return the scaling factor of the value (the number of decimal digits). + /// @return the scaling factor, ranging from 0 to max_scale(). + UInt32 Scale { get; }; + + /// Return the sign of the value. + /// @return 0 if this os zero, <0 if this is less than zero or >0 if this is greater than zero. + Int32 Sign { get; }; + + /// Return the maximum scaling factor + static UInt32 MaxScale{ get; }; + + /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). + static Decimal MaxValue{ get; }; + + /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335). + static Decimal MinValue{ get; }; + + /// Return a decimal whose value is (-this). + Decimal Negate(); + + /// Return the absolute value. + Decimal Abs(); + + /// Return the value's integer portion (zero to the right of the decimal point). + Decimal Fix(); + + /// Return the value rounded down to the nearest integer. + Decimal Integer(); + + /// Return the value rounded to the specific number of decimal places. + Decimal Round(Int32 decimalPlaces); + + /// Returns a Decimal whose value is (this + value). + Decimal Add(Decimal value); + + /// Returns a Decimal whose value is (this - value). + Decimal Sub(Decimal value); + + /// Returns a Decimal whose value is (this * value). + Decimal Mul(Decimal value); + + /// Returns a Decimal whose value is (this / value). + Decimal Div(Decimal value); + + /// Returns a Decimal whose value is (this % value). + Decimal Mod(Decimal value); + } +} diff --git a/dev/Decimal/Decimal.vcxitems b/dev/Decimal/Decimal.vcxitems new file mode 100644 index 0000000000..54e8d4ec1f --- /dev/null +++ b/dev/Decimal/Decimal.vcxitems @@ -0,0 +1,32 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {dc453de3-18fd-43e7-8103-20763c8b97c8} + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/Decimal/Decimal.vcxitems.filters b/dev/Decimal/Decimal.vcxitems.filters new file mode 100644 index 0000000000..f4db261b5a --- /dev/null +++ b/dev/Decimal/Decimal.vcxitems.filters @@ -0,0 +1,32 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + + diff --git a/dev/Decimal/DecimalTelemetry.h b/dev/Decimal/DecimalTelemetry.h new file mode 100644 index 0000000000..f9b283bbe0 --- /dev/null +++ b/dev/Decimal/DecimalTelemetry.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT license. + +#pragma once + +#include + +DECLARE_TRACELOGGING_CLASS(DecimalTelemetryProvider, + "Microsoft.WindowsAppSDK.DecimalTelemetry", + // {a4ed7638-2f9b-4fdf-a06a-d6cd26ff309d} + (0xa4ed7638, 0x2f9b, 0x4fdf, 0xa0, 0x6a, 0xd6, 0xcd, 0x26, 0xff, 0x30, 0x9d)); + +class DecimalTelemetry : public wil::TraceLoggingProvider +{ + IMPLEMENT_TELEMETRY_CLASS(DecimalTelemetry, DecimalTelemetryProvider); + +public: + + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(ToDo, PDT_ProductAndServicePerformance); + END_ACTIVITY_CLASS(); +}; diff --git a/dev/Decimal/M.W.F.Decimal.cpp b/dev/Decimal/M.W.F.Decimal.cpp new file mode 100644 index 0000000000..a1c8da8562 --- /dev/null +++ b/dev/Decimal/M.W.F.Decimal.cpp @@ -0,0 +1,304 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "M.W.F.Decimal.h" +#include "Microsoft.Windows.Foundation.Decimal.g.cpp" + +#include "DecimalTelemetry.h" + +namespace winrt::Microsoft::Windows::Foundation::implementation +{ + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromBoolean(bool value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromInt16(int16_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromInt32(int32_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromInt64(int64_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromUInt8(uint8_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromUInt16(uint16_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromUInt32(uint32_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromUInt64(uint64_t value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromSingle(float value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromDouble(double value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromString(hstring const& value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromStringWithSystemDefaultLocale(hstring const& value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value, LOCALE_SYSTEM_DEFAULT)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromStringWithUserDefaultLocale(hstring const& value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value, LOCALE_USER_DEFAULT)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromStringWithThreadLocale(hstring const& value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value, GetThreadLocale())); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromStringWithInvariantLocale(hstring const& value) + { + return winrt::make(::Microsoft::Windows::Foundation::decimal(value, LOCALE_INVARIANT)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Create(winrt::Windows::Foundation::IInspectable const& value) + { + throw hresult_not_implemented(); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromDecimal(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(to_decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::CreateFromDecimalValue(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) + { + return winrt::make(to_decimal(value)); + } + uint32_t Decimal::MaxScale() + { + return ::Microsoft::Windows::Foundation::decimal::max_scale(); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::MaxValue() + { + const auto value{ ::Microsoft::Windows::Foundation::decimal::max_value() }; + return winrt::make(value); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::MinValue() + { + const auto value{ ::Microsoft::Windows::Foundation::decimal::min_value() }; + return winrt::make(value); + } + void Decimal::SetFromBoolean(bool value) + { + m_decimal = value; + } + void Decimal::SetFromInt16(int16_t value) + { + m_decimal = value; + } + void Decimal::SetFromInt32(int32_t value) + { + m_decimal = value; + } + void Decimal::SetFromInt64(int64_t value) + { + m_decimal = value; + } + void Decimal::SetFromUInt8(uint8_t value) + { + m_decimal = value; + } + void Decimal::SetFromUInt16(uint16_t value) + { + m_decimal = value; + } + void Decimal::SetFromUInt32(uint32_t value) + { + m_decimal = value; + } + void Decimal::SetFromUInt64(uint64_t value) + { + m_decimal = value; + } + void Decimal::SetFromSingle(float value) + { + m_decimal = value; + } + void Decimal::SetFromDouble(double value) + { + m_decimal = value; + } + void Decimal::SetFromString(hstring const& value) + { + ::Microsoft::Windows::Foundation::decimal decimal{ value }; + m_decimal = decimal; + } + void Decimal::SetFromStringWithSystemDefaultLocale(hstring const& value) + { + ::Microsoft::Windows::Foundation::decimal decimal(value, LOCALE_SYSTEM_DEFAULT); + m_decimal = decimal; + } + void Decimal::SetFromStringWithUserDefaultLocale(hstring const& value) + { + ::Microsoft::Windows::Foundation::decimal decimal(value, LOCALE_USER_DEFAULT); + m_decimal = decimal; + } + void Decimal::SetFromStringWithThreadLocale(hstring const& value) + { + ::Microsoft::Windows::Foundation::decimal decimal(value, GetThreadLocale()); + m_decimal = decimal; + } + void Decimal::SetFromStringWithInvariantLocale(hstring const& value) + { + ::Microsoft::Windows::Foundation::decimal decimal(value, LOCALE_INVARIANT); + m_decimal = decimal; + } + void Decimal::Set(winrt::Windows::Foundation::IInspectable const& value) + { + throw hresult_not_implemented(); + } + void Decimal::SetFromDecimal(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + SetFromDecimalValue(value.ToDecimalValue()); + } + void Decimal::SetFromDecimalValue(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) + { + m_decimal = std::bit_cast(value); + } + bool Decimal::ToBoolean() + { + return m_decimal.to_bool(); + } + int16_t Decimal::ToInt16() + { + return m_decimal.to_int16(); + } + int32_t Decimal::ToInt32() + { + return m_decimal.to_int32(); + } + int64_t Decimal::ToInt64() + { + return m_decimal.to_int64(); + } + uint8_t Decimal::ToUInt8() + { + return m_decimal.to_uint8(); + } + uint16_t Decimal::ToUInt16() + { + return m_decimal.to_uint16(); + } + uint32_t Decimal::ToUInt32() + { + return m_decimal.to_uint32(); + } + uint64_t Decimal::ToUInt64() + { + return m_decimal.to_uint64(); + } + float Decimal::ToSingle() + { + return m_decimal.to_float(); + } + double Decimal::ToDouble() + { + return m_decimal.to_double(); + } + hstring Decimal::ToStringWithSystemDefaultLocale() + { + return m_decimal.to_hstring(LOCALE_SYSTEM_DEFAULT); + } + hstring Decimal::ToStringWithUserDefaultLocale() + { + return m_decimal.to_hstring(LOCALE_USER_DEFAULT); + } + hstring Decimal::ToStringWithThreadLocale() + { + return m_decimal.to_hstring(GetThreadLocale()); + } + hstring Decimal::ToStringWithInvariantLocale() + { + return m_decimal.to_hstring(LOCALE_INVARIANT); + } + winrt::Windows::Foundation::IInspectable Decimal::ToObject() + { + throw hresult_not_implemented(); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::ToDecimal() + { + return winrt::make(m_decimal); + } + winrt::Microsoft::Windows::Foundation::DecimalValue Decimal::ToDecimalValue() + { + return to_DecimalValue(m_decimal); + } + int32_t Decimal::Compare(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return m_decimal.compare(to_DECIMAL(value)); + } + bool Decimal::Equals(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return m_decimal == to_DECIMAL(value); + } + uint32_t Decimal::Scale() + { + return m_decimal.scale(); + } + int32_t Decimal::Sign() + { + return m_decimal.sign(); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Negate() + { + return winrt::make(-m_decimal); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Abs() + { + return winrt::make(m_decimal.abs()); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Fix() + { + return winrt::make(m_decimal.fix()); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Integer() + { + return winrt::make(m_decimal.integer()); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Round(int32_t decimalPlaces) + { + return winrt::make(m_decimal.round(decimalPlaces)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Add(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(m_decimal + to_decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Sub(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(m_decimal - to_decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Mul(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(m_decimal * to_decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Div(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(m_decimal / to_decimal(value)); + } + winrt::Microsoft::Windows::Foundation::Decimal Decimal::Mod(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + return winrt::make(m_decimal % to_decimal(value)); + } + hstring Decimal::ToString() + { + return m_decimal.to_hstring(); + } +} diff --git a/dev/Decimal/M.W.F.Decimal.h b/dev/Decimal/M.W.F.Decimal.h new file mode 100644 index 0000000000..61b047095c --- /dev/null +++ b/dev/Decimal/M.W.F.Decimal.h @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Foundation.Decimal.g.h" + +#include +#include + +namespace winrt::Microsoft::Windows::Foundation::implementation +{ + struct Decimal : DecimalT + { + Decimal() = default; + + Decimal(::Microsoft::Windows::Foundation::decimal const& value) : + m_decimal(value) + { + } + + Decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) : + m_decimal(to_DECIMAL(value)) + { + } + + Decimal(DECIMAL const& value) : + m_decimal(value) + { + } + + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromBoolean(bool value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromInt16(int16_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromInt32(int32_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromInt64(int64_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromUInt8(uint8_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromUInt16(uint16_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromUInt32(uint32_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromUInt64(uint64_t value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromSingle(float value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromDouble(double value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromString(hstring const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromStringWithSystemDefaultLocale(hstring const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromStringWithUserDefaultLocale(hstring const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromStringWithThreadLocale(hstring const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromStringWithInvariantLocale(hstring const& value); + static winrt::Microsoft::Windows::Foundation::Decimal Create(winrt::Windows::Foundation::IInspectable const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromDecimal(winrt::Microsoft::Windows::Foundation::Decimal const& value); + static winrt::Microsoft::Windows::Foundation::Decimal CreateFromDecimalValue(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); + static uint32_t MaxScale(); + static winrt::Microsoft::Windows::Foundation::Decimal MaxValue(); + static winrt::Microsoft::Windows::Foundation::Decimal MinValue(); + void SetFromBoolean(bool value); + void SetFromInt16(int16_t value); + void SetFromInt32(int32_t value); + void SetFromInt64(int64_t value); + void SetFromUInt8(uint8_t value); + void SetFromUInt16(uint16_t value); + void SetFromUInt32(uint32_t value); + void SetFromUInt64(uint64_t value); + void SetFromSingle(float value); + void SetFromDouble(double value); + void SetFromString(hstring const& value); + void SetFromStringWithSystemDefaultLocale(hstring const& value); + void SetFromStringWithUserDefaultLocale(hstring const& value); + void SetFromStringWithThreadLocale(hstring const& value); + void SetFromStringWithInvariantLocale(hstring const& value); + void Set(winrt::Windows::Foundation::IInspectable const& value); + void SetFromDecimal(winrt::Microsoft::Windows::Foundation::Decimal const& value); + void SetFromDecimalValue(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); + bool ToBoolean(); + int16_t ToInt16(); + int32_t ToInt32(); + int64_t ToInt64(); + uint8_t ToUInt8(); + uint16_t ToUInt16(); + uint32_t ToUInt32(); + uint64_t ToUInt64(); + float ToSingle(); + double ToDouble(); + hstring ToStringWithSystemDefaultLocale(); + hstring ToStringWithUserDefaultLocale(); + hstring ToStringWithThreadLocale(); + hstring ToStringWithInvariantLocale(); + winrt::Windows::Foundation::IInspectable ToObject(); + winrt::Microsoft::Windows::Foundation::Decimal ToDecimal(); + winrt::Microsoft::Windows::Foundation::DecimalValue ToDecimalValue(); + bool Equals(winrt::Microsoft::Windows::Foundation::Decimal const& value); + int32_t Compare(winrt::Microsoft::Windows::Foundation::Decimal const& value); + uint32_t Scale(); + int32_t Sign(); + winrt::Microsoft::Windows::Foundation::Decimal Negate(); + winrt::Microsoft::Windows::Foundation::Decimal Abs(); + winrt::Microsoft::Windows::Foundation::Decimal Fix(); + winrt::Microsoft::Windows::Foundation::Decimal Integer(); + winrt::Microsoft::Windows::Foundation::Decimal Round(int32_t decimalPlaces); + winrt::Microsoft::Windows::Foundation::Decimal Add(winrt::Microsoft::Windows::Foundation::Decimal const& value); + winrt::Microsoft::Windows::Foundation::Decimal Sub(winrt::Microsoft::Windows::Foundation::Decimal const& value); + winrt::Microsoft::Windows::Foundation::Decimal Mul(winrt::Microsoft::Windows::Foundation::Decimal const& value); + winrt::Microsoft::Windows::Foundation::Decimal Div(winrt::Microsoft::Windows::Foundation::Decimal const& value); + winrt::Microsoft::Windows::Foundation::Decimal Mod(winrt::Microsoft::Windows::Foundation::Decimal const& value); + hstring ToString(); + + private: + ::Microsoft::Windows::Foundation::decimal m_decimal; + }; +} +namespace winrt::Microsoft::Windows::Foundation::factory_implementation +{ + struct Decimal : DecimalT + { + }; +} diff --git a/dev/Decimal/decimal.h b/dev/Decimal/decimal.h new file mode 100644 index 0000000000..2d1557ca1c --- /dev/null +++ b/dev/Decimal/decimal.h @@ -0,0 +1,703 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef DECIMAL_H +#define DECIMAL_H + +#include + +#if !defined(_VC_NODEFAULTLIB) +#pragma comment(linker, "/defaultlib:oleaut32.lib") +#endif + +inline int compare(const DECIMAL& left, const DECIMAL& right) +{ + static_assert(VARCMP_LT == 0, "VARCMP_LT == 0"); + static_assert(VARCMP_EQ == 1, "VARCMP_EQ == 1"); + static_assert(VARCMP_GT == 2, "VARCMP_GT == 2"); + return ::VarDecCmp(const_cast(&left), const_cast(&right)) - 1; +} + +inline bool operator==(const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) == 0; +} + +inline bool operator!=(const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) != 0; +} + +inline bool operator< (const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) < 0; +} + +inline bool operator<=(const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) <= 0; +} + +inline bool operator> (const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) > 0; +} + +inline bool operator>=(const DECIMAL& left, const DECIMAL& right) +{ + return compare(left, right) >= 0; +} + +namespace Microsoft::Windows::Foundation +{ +class decimal +{ +public: + decimal() = default; + ~decimal() = default; + + decimal(const decimal& value) : + m_decimal(value.m_decimal) + { + } + + decimal(decimal&& value) : + m_decimal(value.m_decimal) + { + value.m_decimal = DECIMAL{}; + } + + constexpr decimal(const DECIMAL& value) : + m_decimal(value) + { + } + + decimal(bool value) + { + // VARIANT_TRUE is weird by today's standards: + // typedef short VARIANT_BOOL; + // #define VARIANT_TRUE ((VARIANT_BOOL) 0xffff) + // #define VARIANT_FALSE ((VARIANT_BOOL) 0) + // Thus + // VarDecFromBool(VARIANT_TRUE) == -1 + // VarDecFromBool(VARIANT_FALSE) == 0 + // But decimal(true) would be expected to be 1 (not -1) + // So we intentionally ignore VarDecFromBool() and set decimal(bool) == 0 or 1 + THROW_IF_FAILED(::VarDecFromUI4(value ? 1 : 0, &m_decimal)); + } + + decimal(char value) + { + THROW_IF_FAILED(::VarDecFromI1(value, &m_decimal)); + } + + decimal(std::int16_t value) + { + THROW_IF_FAILED(::VarDecFromI2(value, &m_decimal)); + } + + decimal(std::int32_t value) + { + THROW_IF_FAILED(::VarDecFromI4(value, &m_decimal)); + } + + decimal(std::int64_t value) + { + THROW_IF_FAILED(::VarDecFromI8(value, &m_decimal)); + } + + decimal(std::uint8_t value) + { + THROW_IF_FAILED(::VarDecFromUI1(value, &m_decimal)); + } + + decimal(std::uint16_t value) + { + THROW_IF_FAILED(::VarDecFromUI2(value, &m_decimal)); + } + + decimal(std::uint32_t value) + { + THROW_IF_FAILED(::VarDecFromUI4(value, &m_decimal)); + } + + decimal(std::uint64_t value) + { + THROW_IF_FAILED(::VarDecFromUI8(value, &m_decimal)); + } + + decimal(float value) + { + THROW_IF_FAILED(::VarDecFromR4(value, &m_decimal)); + } + + decimal(double value) + { + THROW_IF_FAILED(::VarDecFromR8(value, &m_decimal)); + } + + decimal(long value) + { + THROW_IF_FAILED(::VarDecFromI4(value, &m_decimal)); + } + + decimal(unsigned long value) + { + THROW_IF_FAILED(::VarDecFromUI4(value, &m_decimal)); + } + + decimal(PCWSTR value) + { + THROW_IF_FAILED(::VarDecFromStr(value, LOCALE_INVARIANT, 0, &m_decimal)); + } + + decimal(PCWSTR value, const LCID locale) + { + THROW_IF_FAILED(::VarDecFromStr(value, locale, 0, &m_decimal)); + } + + decimal(const std::wstring& value) + { + THROW_IF_FAILED(::VarDecFromStr(value.c_str(), LOCALE_INVARIANT, 0, &m_decimal)); + } + + decimal(const std::wstring& value, const LCID locale) + { + THROW_IF_FAILED(::VarDecFromStr(value.c_str(), locale, 0, &m_decimal)); + } + +#if defined(WINRT_BASE_H) + decimal(const winrt::hstring& value) + { + THROW_IF_FAILED(::VarDecFromStr(value.c_str(), LOCALE_INVARIANT, 0, &m_decimal)); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + decimal(const winrt::hstring& value, const LCID locale) + { + THROW_IF_FAILED(::VarDecFromStr(value.c_str(), locale, 0, &m_decimal)); + } +#endif // defined(WINRT_BASE_H) + + decimal& operator=(const decimal& value) + { + if (&value != this) + { + m_decimal = value.m_decimal; + } + return *this; + } + + decimal& operator=(decimal&& value) + { + if (&value != this) + { + m_decimal = value.m_decimal; + value.m_decimal = DECIMAL{}; + } + return *this; + } + + decimal& operator=(const DECIMAL& value) + { + if (&value != &m_decimal) + { + m_decimal = value; + } + return *this; + } + + decimal& operator=(bool value) + { + // VARIANT_TRUE is weird by today's standards: + // typedef short VARIANT_BOOL; + // #define VARIANT_TRUE ((VARIANT_BOOL) 0xffff) + // #define VARIANT_FALSE ((VARIANT_BOOL) 0) + // Thus + // VarDecFromBool(VARIANT_TRUE) == -1 + // VarDecFromBool(VARIANT_FALSE) == 0 + // But decimal(true) would be expected to be 1 (not -1) + // So we intentionally ignore VarDecFromBool() and set decimal(bool) == 0 or 1 + THROW_IF_FAILED(::VarDecFromUI4(value ? 1 : 0, &m_decimal)); + return *this; + } + + decimal& operator=(char value) + { + THROW_IF_FAILED(::VarDecFromI1(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::int16_t value) + { + THROW_IF_FAILED(::VarDecFromI2(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::int32_t value) + { + THROW_IF_FAILED(::VarDecFromI4(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::int64_t value) + { + THROW_IF_FAILED(::VarDecFromI8(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::uint8_t value) + { + THROW_IF_FAILED(::VarDecFromUI1(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::uint16_t value) + { + THROW_IF_FAILED(::VarDecFromUI2(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::uint32_t value) + { + THROW_IF_FAILED(::VarDecFromUI4(value, &m_decimal)); + return *this; + } + + decimal& operator=(std::uint64_t value) + { + THROW_IF_FAILED(::VarDecFromUI8(value, &m_decimal)); + return *this; + } + + decimal& operator=(float value) + { + THROW_IF_FAILED(::VarDecFromR4(value, &m_decimal)); + return *this; + } + + decimal& operator=(double value) + { + THROW_IF_FAILED(::VarDecFromR8(value, &m_decimal)); + return *this; + } + + decimal& operator=(long value) + { + THROW_IF_FAILED(::VarDecFromI4(value, &m_decimal)); + return *this; + } + + decimal& operator=(unsigned long value) + { + THROW_IF_FAILED(::VarDecFromUI4(value, &m_decimal)); + return *this; + } + + decimal& operator=(PCWSTR value) + { + THROW_IF_FAILED(::VarDecFromStr(value, LOCALE_INVARIANT, 0, &m_decimal)); + return *this; + } + + decimal& operator=(const std::wstring& value) + { + return operator=(value.c_str()); + } + +#if defined(WINRT_BASE_H) + decimal& operator=(const winrt::hstring& value) + { + return operator=(value.c_str()); + } +#endif // defined(WINRT_BASE_H) + + const DECIMAL& to_decimal() const + { + // Treat all values != 0 as true (good) + return m_decimal; + } + + bool to_bool() const + { + // Treat values != 0 as true + return (m_decimal.Lo64 != 0) || (m_decimal.Hi32 != 0); + } + + char to_char() const + { + char value{}; + THROW_IF_FAILED(::VarI1FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::int16_t to_int16() const + { + std::int16_t value{}; + THROW_IF_FAILED(::VarI2FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::int32_t to_int32() const + { + return static_cast(to_long()); + } + + std::int64_t to_int64() const + { + std::int64_t value{}; + THROW_IF_FAILED(::VarI8FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::uint8_t to_uint8() const + { + std::uint8_t value{}; + THROW_IF_FAILED(::VarUI1FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::uint16_t to_uint16() const + { + std::uint16_t value{}; + THROW_IF_FAILED(::VarUI2FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::uint32_t to_uint32() const + { + return static_cast(to_ulong()); + } + + std::uint64_t to_uint64() const + { + std::uint64_t value{}; + THROW_IF_FAILED(::VarUI8FromDec(const_cast(&m_decimal), &value)); + return value; + } + + float to_float() const + { + float value{}; + THROW_IF_FAILED(::VarR4FromDec(const_cast(&m_decimal), &value)); + return value; + } + + double to_double() const + { + double value{}; + THROW_IF_FAILED(::VarR8FromDec(const_cast(&m_decimal), &value)); + return value; + } + + long to_long() const + { + long value{}; + THROW_IF_FAILED(::VarI4FromDec(&m_decimal, &value)); + return value; + } + + unsigned long to_ulong() const + { + unsigned long value{}; + THROW_IF_FAILED(::VarUI4FromDec(const_cast(&m_decimal), &value)); + return value; + } + + std::wstring to_string() const + { + return to_string(LOCALE_INVARIANT); + } + + std::wstring to_string(const LCID locale) const + { + wil::unique_bstr bstr; + THROW_IF_FAILED(::VarBstrFromDec(&m_decimal, locale, 0, wil::out_param(bstr))); + return std::wstring{ bstr.get() }; + } + +#if defined(WINRT_BASE_H) + winrt::hstring to_hstring() const + { + return to_hstring(LOCALE_INVARIANT); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + winrt::hstring to_hstring(const LCID locale) const + { + wil::unique_bstr bstr; + THROW_IF_FAILED(::VarBstrFromDec(&m_decimal, locale, 0, wil::out_param(bstr))); + return winrt::hstring{ bstr.get() }; + } +#endif // defined(WINRT_BASE_H) + + bool operator==(const decimal& value) const + { + return compare(value) == 0; + } + + bool operator!=(const decimal& value) const + { + return compare(value) != 0; + } + + bool operator< (const decimal& value) const + { + return compare(value) < 0; + } + + bool operator<=(const decimal& value) const + { + return compare(value) <= 0; + } + + bool operator> (const decimal& value) const + { + return compare(value) > 0; + } + + bool operator>=(const decimal& value) const + { + return compare(value) >= 0; + } + + int compare(const decimal& value) const + { + return compare(value.m_decimal); + } + + bool operator==(const DECIMAL& value) const + { + return compare(value) == 0; + } + + bool operator!=(const DECIMAL& value) const + { + return compare(value) != 0; + } + + bool operator< (const DECIMAL& value) const + { + return compare(value) < 0; + } + + bool operator<=(const DECIMAL& value) const + { + return compare(value) <= 0; + } + + bool operator> (const DECIMAL& value) const + { + return compare(value) > 0; + } + + bool operator>=(const DECIMAL& value) const + { + return compare(value) >= 0; + } + + int compare(const DECIMAL& value) const + { + return ::compare(m_decimal, value); + } + + /// Return the scaling factor of the value (the number of decimal digits). + /// @return the scaling factor, ranging from 0 to max_scale(). + std::uint32_t scale() const + { + return m_decimal.scale; + } + + /// Return the sign of the value. + /// @return 0 if this os zero, <0 if this is less than zero or >0 if this is greater than zero. + std::int32_t sign() const + { + return ((m_decimal.Lo64 == 0) && (m_decimal.Hi32 == 0)) ? 0 : (m_decimal.sign != 0 ? -1 : 1); + } + + /// Return the maximum scaling factor + static constexpr std::uint32_t max_scale() + { + return 28; + } + + /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). + static constexpr decimal max_value() + { + DECIMAL value{}; + value.Lo64 = 0xFFFFFFFFFFFFFFFFllu; + value.Hi32 = 0xFFFFFFFFu; + return decimal{ value }; + } + + /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335). + static constexpr decimal min_value() + { + DECIMAL value{}; + value.Lo64 = 0xFFFFFFFFFFFFFFFFllu; + value.Hi32 = 0xFFFFFFFFu; + value.sign = DECIMAL_NEG; + return decimal{ value }; + } + + decimal operator+() const + { + return *this; + } + + decimal operator-() const + { + decimal value{}; + THROW_IF_FAILED(::VarDecNeg(const_cast(&m_decimal), &value.m_decimal)); + return value; + } + + decimal abs() const + { + decimal value{}; + THROW_IF_FAILED(::VarDecAbs(const_cast(&m_decimal), &value.m_decimal)); + return value; + } + + /// Chop to integer. + decimal fix() const + { + decimal value{}; + THROW_IF_FAILED(::VarDecFix(const_cast(&m_decimal), &value.m_decimal)); + return value; + } + + /// Round down to integer. + /// @note this rounds down to -infinity. + decimal integer() const + { + decimal value{}; + THROW_IF_FAILED(::VarDecInt(const_cast(&m_decimal), &value.m_decimal)); + return value; + } + + decimal operator++() + { + return operator+=(decimal(1)); + } + + decimal operator++(int) + { + const decimal before(m_decimal); + operator+=(decimal(1)); + return before; + } + + decimal operator--() + { + return operator-=(decimal(1)); + } + + decimal operator--(int) + { + const decimal before(m_decimal); + operator-=(decimal(1)); + return before; + } + + decimal operator+(const decimal& value) const + { + decimal result{}; + THROW_IF_FAILED(::VarDecAdd(const_cast(&m_decimal), const_cast(&value.m_decimal), &result.m_decimal)); + return result; + } + + decimal& operator+=(const decimal& value) + { + *this = operator+(value); + return *this; + } + + decimal operator-(const decimal& value) const + { + decimal result{}; + THROW_IF_FAILED(::VarDecSub(const_cast(&m_decimal), const_cast(&value.m_decimal), &result.m_decimal)); + return result; + } + + decimal& operator-=(const decimal& value) + { + *this = operator-(value); + return *this; + } + + decimal operator*(const decimal& value) const + { + decimal result{}; + THROW_IF_FAILED(::VarDecMul(const_cast(&m_decimal), const_cast(&value.m_decimal), &result.m_decimal)); + return result; + } + + decimal& operator*=(const decimal& value) + { + *this = operator*(value); + return *this; + } + + decimal operator/(const decimal& value) const + { + decimal result{}; + THROW_IF_FAILED(::VarDecDiv(const_cast(&m_decimal), const_cast(&value.m_decimal), &result.m_decimal)); + return result; + } + + decimal& operator/=(const decimal& value) + { + *this = operator/(value); + return *this; + } + + /// Modulo operation using the Truncated method. + /// @note The % operator in C, C#, Rust and other languages use this method. + /// @note The result's sign will match the current value's sign. + /// @see https://en.wikipedia.org/wiki/Modulo + decimal operator%(const decimal& value) const + { + // VarMod() operates on I4 (int32) at best (not even I8 aka int64) + // So let's do it the grade school way and matching .NET's Decimal... + // + // remainder = left % right + // aka + // aleft = ABS(left) + // aright = ABS(right) + // q = (aleft / aright) + // remainder = aleft - (aright * FIX(aleft / aright) * aright) + // remainder = IF left < 0 THEN remainder = -remainder + + const Microsoft::Windows::Foundation::decimal aleft{ abs() }; + const Microsoft::Windows::Foundation::decimal aright{ value.abs() }; + const bool left_is_negative{ m_decimal.sign != 0 }; + + const Microsoft::Windows::Foundation::decimal quotient{ aleft.abs() / aright.abs() }; + const Microsoft::Windows::Foundation::decimal fix{ quotient.fix() }; + const Microsoft::Windows::Foundation::decimal product{ fix * aright }; + const Microsoft::Windows::Foundation::decimal remainder{ aleft - product }; + return left_is_negative ? -remainder : remainder; + } + + decimal& operator%=(const decimal& value) + { + *this = operator%(value); + return *this; + } + + decimal round(const std::int32_t decimalPlaces) const + { + decimal value{}; + THROW_IF_FAILED(::VarDecRound(const_cast(&m_decimal), decimalPlaces, &value.m_decimal)); + return value; + } + +private: + DECIMAL m_decimal{}; +}; +} + +#endif // DECIMAL_H diff --git a/dev/Decimal/decimalcppwinrt.h b/dev/Decimal/decimalcppwinrt.h new file mode 100644 index 0000000000..ee3dcfda12 --- /dev/null +++ b/dev/Decimal/decimalcppwinrt.h @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include + +#if defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WIMRT_M_W_F_DECIMAL_) +#define __WINDOWSAPPSDK_WIMRT_M_W_F_DECIMAL_ + +//---------------------------------------------------------------------- +// WinRT Decimal operators + +inline bool operator==( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) == 0; +} + +inline bool operator!=( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) != 0; +} + +inline bool operator<( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) < 0; +} + +inline bool operator<=( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) <= 0; +} + +inline bool operator>( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) > 0; +} + +inline bool operator>=( + winrt::Microsoft::Windows::Foundation::Decimal const& left, + winrt::Microsoft::Windows::Foundation::Decimal const& right) +{ + return left.Compare(right) >= 0; +} + +//---------------------------------------------------------------------- +// Conversion functions + +namespace winrt::Microsoft::Windows::Foundation +{ +/// Return value as DECIMAL. +inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return std::bit_cast(value); +} + +/// Return value as DECIMAL. +inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::Decimal const& value) +{ + return to_DECIMAL(value.ToDecimalValue()); +} + +/// Return value as a WinRT DecimalValue structure. +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value) +{ + return std::bit_cast(value); +} + +/// Return value as a WinRT Decimal object. +inline winrt::Microsoft::Windows::Foundation::Decimal to_Decimal(DECIMAL const& value) +{ + return winrt::Microsoft::Windows::Foundation::Decimal::CreateFromDecimalValue(to_DecimalValue(value)); +} + +#if defined(DECIMAL_H) && !defined(__WINDOWSAPPSDK_DECIMAL_) +#define __WINDOWSAPPSDK_DECIMAL_ + +/// Return value as a WinRT DecimalValue structure. +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value) +{ + return to_DecimalValue(value.to_decimal()); +} + +/// Return value as a WinRT decimal object. +inline winrt::Microsoft::Windows::Foundation::Decimal to_Decimal(::Microsoft::Windows::Foundation::decimal const& value) +{ + return to_Decimal(value.to_decimal()); +} + +/// Return value as a C++ decimal object. +inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::Decimal const& value) +{ + return ::Microsoft::Windows::Foundation::decimal{ to_DECIMAL(value) }; +} + +/// Return value as a C++ decimal object. +inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return ::Microsoft::Windows::Foundation::decimal{ to_DECIMAL(value) }; +} + +#endif // defined(DECIMAL_H) && !defined(__WINDOWSAPPSDK_DECIMAL_) + +} + +#endif // defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WIMRT_M_W_F_DECIMAL_) diff --git a/dev/Decimal/pch.h b/dev/Decimal/pch.h new file mode 100644 index 0000000000..dbe88742de --- /dev/null +++ b/dev/Decimal/pch.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +#include +#include diff --git a/dev/Projections/CS/Microsoft.Windows.Foundation/DecimalExtensions.cs b/dev/Projections/CS/Microsoft.Windows.Foundation/DecimalExtensions.cs new file mode 100644 index 0000000000..b842aa92a1 --- /dev/null +++ b/dev/Projections/CS/Microsoft.Windows.Foundation/DecimalExtensions.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; +using System.Runtime.CompilerServices; + +using Microsoft.Windows.Foundation; + +namespace Microsoft.Windows.Foundation +{ + public static class DecimalExtensions + { + /// Return a WinRT Decimal object. + public static Microsoft.Windows.Foundation.Decimal ToDecimal(this decimal d) + { + return Microsoft.Windows.Foundation.Decimal.CreateFromDecimalValue(ToDecimalValue(d)); + } + + /// Return a WinRT DecimalValue structure.. + public static Microsoft.Windows.Foundation.DecimalValue ToDecimalValue(this decimal d) + { + // decimal.GetBits() returns a binary representation of a Decimal. The return value is an + // integer array with four elements. Elements 0, 1, and 2 contain the low, + // middle, and high 32 bits of the 96-bit integer part of the Decimal. + // Element 3 contains the scale factor and sign of the Decimal: bits 0-15 + // (the lower word) are unused; bits 16-23 contain a value between 0 and + // 28, indicating the power of 10 to divide the 96-bit integer part by to + // produce the Decimal value; bits 24-30 are unused; and finally bit 31 + // indicates the sign of the Decimal value, 0 meaning positive and 1 + // meaning negative. + // [0] = (int)d.Low; + // [1] = (int)d.Mid; + // [2] = (int)d.High; + // [3] = d._flags; + // where d._flags is 2 bytes reserved, 1 byte sign, 1 byte scale + // + // @see https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/libraries/System.Private.CoreLib/src/System/Decimal.cs#L581C13-L581C80 + + Span bits = stackalloc int[4]; + decimal.GetBits(d, bits); + + var decimalValue = new Microsoft.Windows.Foundation.DecimalValue(); + decimalValue.Sign = (byte)((bits[3] & 0x80000000) >> 24); + decimalValue.Scale = (byte)((bits[3] & 0x00FF0000) >> 16); + decimalValue.Hi32 = (uint)bits[2]; + ulong low32 = (ulong)bits[0]; + ulong mid32 = (ulong)bits[1]; + decimalValue.Lo64 = ((low32 << 32) | mid32); + return decimalValue; + } + + /// Return a C# Decimal object. + public static decimal FromDecimalValue(this decimal d, Microsoft.Windows.Foundation.DecimalValue value) + { + int low32 = (int)(value.Lo64 & 0x00000000FFFFFFFF); + int mid32 = (int)((value.Lo64 >> 32) & 0x00000000FFFFFFFF); + return new decimal(low32, mid32, (int)value.Hi32, value.Sign != 0, value.Scale); + } + + /// Return a C# Decimal object. + public static decimal FromDecimal(this decimal d, Microsoft.Windows.Foundation.Decimal value) + { + return FromDecimalValue(d, value.ToDecimalValue()); + } + } +} diff --git a/dev/Projections/CS/Microsoft.Windows.Foundation/Microsoft.Windows.Foundation.Projection.csproj b/dev/Projections/CS/Microsoft.Windows.Foundation/Microsoft.Windows.Foundation.Projection.csproj new file mode 100644 index 0000000000..af2923c8eb --- /dev/null +++ b/dev/Projections/CS/Microsoft.Windows.Foundation/Microsoft.Windows.Foundation.Projection.csproj @@ -0,0 +1,58 @@ + + + net6.0-windows10.0.17763.0 + 10.0.17763.0 + x64;x86;arm64 + AnyCPU + false + + + + true + true + + + + + 8305 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + Microsoft.Windows.Foundation + 10.0.17763.0 + false + + + + + pdbonly + true + + + + + + + + + + + + + $(OutDir)..\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Foundation.winmd + true + + + diff --git a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj index c5ac889f59..a0b5a2c924 100644 --- a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj +++ b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj @@ -106,6 +106,7 @@ + @@ -330,4 +331,4 @@ - \ No newline at end of file + diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md new file mode 100644 index 0000000000..cf72dfeaff --- /dev/null +++ b/specs/decimal/decimal.md @@ -0,0 +1,262 @@ +# 1. Decimal + +THIS FEATURE IS CURRENTLY EXPERIMENTAL. + +This feature provides a common decimal representation and aids for use within and across programming languages. + +Some languages have a native decimal data type, e.g. [Decimal struct in C#](https://learn.microsoft.com/dotnet/api/system.decimal) +and [decimal in Python](https://docs.python.org/3/library/decimal.html). These are recommended for +use in their languages. Windows App SDK provides supplemental aids for interoperability with the +common data type. + +Other languages have no native decimal data type e.g. C++, Rust and Javascript. Windows App SDK +provides language native support for some languages including interoperability with the common data +type: + +* C++ -- `Microsoft::Windows::Foundation::decimal` + +Windows App SDK provides a decimal WinRT runtimeclass `Microsoft.Windows.Foundation.Decimal` as a +fallback for languages without a native decimal data type (whether provided by the language or +Windows App SDK). This is fully functional but has performance overhead relative to language native +data types which are commonly stack allocated and offer better language integration. The WinRT type +is recommended when your language has no native type or other comparable solution. + +# 2. Common Decimal Representation + +The Win32 [DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) +structure is the common decimal format, stored as a 96-bit (12-byte) unsigned integer scaled by a +variable power of 10. The power of 10 scaling factor specifies the number of digits to the right of +the decimal point, and ranges from 0 to 28. This is expressed in WinRT as the following structure: + +```c# (but really midl3) + struct DecimalValue + { + UInt16 Reserved; + Byte Scale; // Allowed values: 0-28 + Byte Sign; // Allowed values: 0x80 = negative, 0x00 = zero or positive + UInt32 Hi32; + UInt64 Lo64; + } +``` + +This matches the memory layout and use of the Win32 [DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) +structure and the [C# Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal). This +data structure may be re-expressed in each language using language-specific constructs e.g. WinRT +defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with +WinRT IDL. + +# 3. WinRT API + +Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure. + +```c# (but really MIDL3) +namespace Microsoft.Windows.Foundation +{ + [contractversion(1)] + apicontract DecimalContract{}; + + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + struct DecimalValue + { + UInt16 Reserved; + UInt8 Scale; // Allowed values: 0-28 + UInt8 Sign; // Allowed values: 0x80 = negative, 0x00 = zero or positive + UInt32 Hi32; + UInt64 Lo64; + }; + + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + runtimeclass Decimal : Windows.Foundation.IStringable + { + Decimal(); + + static Decimal CreateFromBoolean(Boolean value); + static Decimal CreateFromInt16(Int16 value); + static Decimal CreateFromInt32(Int32 value); + static Decimal CreateFromInt64(Int64 value); + static Decimal CreateFromUInt8(UInt8 value); + static Decimal CreateFromUInt16(UInt16 value); + static Decimal CreateFromUInt32(UInt32 value); + static Decimal CreateFromUInt64(UInt64 value); + static Decimal CreateFromSingle(Single value); + static Decimal CreateFromDouble(Double value); + static Decimal CreateFromString(String value); // LCID=LOCALE_INVARIANT + static Decimal CreateFromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() + static Decimal CreateFromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() + static Decimal CreateFromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + static Decimal CreateFromStringWithInvariantLocale(String value); // LCID=LOCALE_INVARIANT + static Decimal Create(IInspectable value); + static Decimal CreateFromDecimal(Decimal value); + static Decimal CreateFromDecimalValue(DecimalValue value); + + void SetFromBoolean(Boolean value); + void SetFromInt16(Int16 value); + void SetFromInt32(Int32 value); + void SetFromInt64(Int64 value); + void SetFromUInt8(UInt8 value); + void SetFromUInt16(UInt16 value); + void SetFromUInt32(UInt32 value); + void SetFromUInt64(UInt64 value); + void SetFromSingle(Single value); + void SetFromDouble(Double value); + void SetFromString(String value); // LCID=LOCALE_INVARIANT + void SetFromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() + void SetFromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() + void SetFromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + void SetFromStringWithInvariantLocale(String value); // LCID=LOCALE_INVARIANT + void Set(IInspectable value); + void SetFromDecimal(Decimal value); + void SetFromDecimalValue(DecimalValue value); + + Boolean ToBoolean(); + Int16 ToInt16(); + Int32 ToInt32(); + Int64 ToInt64(); + UInt8 ToUInt8(); + UInt16 ToUInt16(); + UInt32 ToUInt32(); + UInt64 ToUInt64(); + Single ToSingle(); + Double ToDouble(); + //String ToString(); inherited from IStringable // LCID=LOCALE_INVARIANT + String ToStringWithSystemDefaultLocale(); // LCID=GetSystemDefaultLCID() + String ToStringWithUserDefaultLocale(); // LCID=GetUserDefaultLCID() + String ToStringWithThreadLocale(); // LCID=GetThreadLocale() + String ToStringWithInvariantLocale(); // LCID=LOCALE_INVARIANT + IInspectable ToObject(); + Decimal ToDecimal(); //TODO: Rename to Copy(value) or Clone(value) ? + DecimalValue ToDecimalValue(); + + /// Return true if (this == value). + Boolean Equals(Decimal value); + + /// Compare this decimal with value. + /// @return 0 if this and value are equal, <0 if this is less than value or >0 if this is greater than value. + Int32 Compare(Decimal value); + + /// Return the scaling factor of the value (the number of decimal digits). + /// @return the scaling factor, ranging from 0 to max_scale(). + UInt32 Scale { get; }; + + /// Return the sign of the value. + /// @return 0 if this os zero, <0 if this is less than zero or >0 if this is greater than zero. + Int32 Sign { get; }; + + /// Return the maximum scaling factor + static UInt32 MaxScale{ get; }; + + /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). + static Decimal MaxValue{ get; }; + + /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335). + static Decimal MinValue{ get; }; + + /// Return a decimal whose value is (-this). + Decimal Negate(); + + /// Return the absolute value. + Decimal Abs(); + + /// Return the value's integer portion (zero to the right of the decimal point). + Decimal Fix(); + + /// Return the value rounded down to the nearest integer. + Decimal Integer(); + + /// Return the value rounded to the specific number of decimal places. + Decimal Round(Int32 decimalPlaces); + + /// Returns a Decimal whose value is (this + value). + Decimal Add(Decimal value); + + /// Returns a Decimal whose value is (this - value). + Decimal Sub(Decimal value); + + /// Returns a Decimal whose value is (this * value). + Decimal Mul(Decimal value); + + /// Returns a Decimal whose value is (this / value). + Decimal Div(Decimal value); + + /// Returns a Decimal whose value is (this % value). + Decimal Mod(Decimal value); + } +} +``` + +# 4. C++ API + +Windows App SDK provides a native language decimal data type for C++ as the +`Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: + +* Constructor and assignment (operator=) overloads to define a decimal object from various data types +* to_xxx() methods converting a decimal object's value to various data types +* Relational operations: `compare()` `==` `!=` `<` `<=` `>` `>=` +* Unary operations: + - ++ -- +* Binary operations: + += - -= * *= / /= % %= +* Properties: `sign()` `scale()` +* Mathematical operations: `abs()` `fix()` `integer()` `round()` +* Constants: `max_scale()` `max_value()` `min_value()` + +Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception + +## 4.1. Microsoft.Windows.Foundation (C++) + +TODO insert header filename(s) and API here + +# 6. Open Issues + +# 6.1. API Review + +Potential changes for API Review consideration: + +1. String conversions - How to handle + 1. VarDecFromStr() and VarBStrFromDec() support localization via LCID. WinRT doesn't. + 1. Support LCID for localization? + 1. C++ has to/from string with taking (value, LCID) with default LCID=LOCALE_INVARIANT + 2. WinRT has pre-canned variants: + 1. ToStringWithSystemDefaultLocale(); // LCID=GetSystemDefaultLCID() + 2. ToStringWithUserDefaultLocale(); // LCID=GetUserDefaultLCID() + 3. ToStringWithThreadLocale(); // LCID=GetThreadLocale() + 4. ToStringWithInvariantLocale(); // LCID=LOCALE_INVARIANT + 5. ToString() == ToStringWithInvariantLocale() + 2. Use alternative ??? for localization? + 1. ??? <-> LCID conversion APIs? + 2. Rewrite VarDecFromStr() and VBstrFromDec() as equivalents using ??? +2. C++ class + 1. Add floor() - round towards +infinity. https://learn.microsoft.com/en-us/dotnet/api/system.decimal.floor + 2. Add ceil() - round towards -infinity. https://learn.microsoft.com/en-us/dotnet/api/system.decimal.ceiling + 1. Rename integer() to ceil() ? + 3. Add floor-ceil-variant() - round towards zero +3. winrt::Microsoft::Windows::Foundation::Decimal + 1. Rename ToDecimal() to Copy(value) or Clone(value) + 2. Add Floor() + 3. Rename Integer() to Ceil() + 4. Add Floor-Ceil-Variant() for rounds towards zero + 5. Rename Sub() to Subtract() + 6. Rename Mul() to Multiply() + 7. Rename Div() to Divide() + 8. Rename Mod() to Remainder() + +# 6.2. TODO + +Punchlist to reach Stable: + +1. C++ class + 1. BUG? decimal zero{}; decimal neg{ -zero }; neg.sign() < 0 because DECIMAL.sign = 0x80. Treat -0 the same as +0 (prevent -0 from being set?) +2. winrt::Microsoft::Windows::Foundation::Decimal + 1. Implement IInspectable methods -- Create(IInspectable), Set(IInspectable), ToObject() + 2. Add experimental checks in ctor + static methods +3. decimalcppwinrt.h + 1. Merge into decimal.h +4. Microsoft.Windows.Foundation.Projection + 1. --none-- +5. C# Tests + 1. TAEF for C# ? + 2. Port test\inc\WindowsAppRuntime.Test.Package.h to C# + 3. Port test\inc\WindowsAppRuntime.Test.Bootstrap.h to C# + 4. Register framework package + 5. Bootstrap.Initialize() + 6. Implement remaining tests diff --git a/test/Decimal/CPP/DecimalTests.cpp b/test/Decimal/CPP/DecimalTests.cpp new file mode 100644 index 0000000000..942d5d8e27 --- /dev/null +++ b/test/Decimal/CPP/DecimalTests.cpp @@ -0,0 +1,1563 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +namespace TD = ::Test::Diagnostics; +namespace TB = ::Test::Bootstrap; +namespace TP = ::Test::Packages; +namespace TD = ::Test::Diagnostics; + +namespace WEX::TestExecution +{ + // Teach TAEF how to format a Microsoft::Windows::Foundation::decimal + template <> + class VerifyOutputTraits + { + public: + static WEX::Common::NoThrowString ToString(Microsoft::Windows::Foundation::decimal const& value) + { + const auto s{ value.to_string() }; + return WEX::Common::NoThrowString().Format(L"\"%s\"", s.c_str()); + } + }; + + // Teach TAEF how to compare a Microsoft::Windows::Foundation::decimal + template <> + class VerifyCompareTraits + { + public: + static bool AreEqual(Microsoft::Windows::Foundation::decimal const& expected, Microsoft::Windows::Foundation::decimal const& actual) + { + return expected == actual; + } + + static bool AreSame(Microsoft::Windows::Foundation::decimal const& expected, Microsoft::Windows::Foundation::decimal const& actual) + { + return &expected == &actual; + } + + static bool IsLessThan(Microsoft::Windows::Foundation::decimal const& expectedLess, Microsoft::Windows::Foundation::decimal const& expectedGreater) + { + return expectedLess < expectedGreater; + } + + static bool IsGreaterThan(Microsoft::Windows::Foundation::decimal const& expectedGreater, Microsoft::Windows::Foundation::decimal const& expectedLess) + { + return expectedGreater > expectedLess; + } + + static bool IsNull(Microsoft::Windows::Foundation::decimal const& /*object*/) + { + return false; + } + }; +} + +namespace Test::Decimal::Tests +{ + class DecimalTests + { + public: + BEGIN_TEST_CLASS(DecimalTests) + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + TEST_CLASS_PROPERTY(L"RunAs", L"RestrictedUser") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + ::TD::DumpExecutionContext(); + ::TB::Setup(TB::Packages::Framework); + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + ::TB::Cleanup(); + return true; + } + + TEST_METHOD(ctor) + { + const std::int64_t data{}; + Microsoft::Windows::Foundation::decimal decimal; + const auto value{ decimal.to_int64() }; + VERIFY_ARE_EQUAL(data, value); + } + + TEST_METHOD(ctor_assign_move) + { + const Microsoft::Windows::Foundation::decimal data{ -1234567890 }; + const Microsoft::Windows::Foundation::decimal zero{}; + + Microsoft::Windows::Foundation::decimal before{ data }; + VERIFY_ARE_EQUAL(data, before); + const Microsoft::Windows::Foundation::decimal after = std::move(before); + VERIFY_ARE_EQUAL(data, after); + VERIFY_ARE_EQUAL(zero, before); + } + + TEST_METHOD(ctor_to_assign_decimal) + { + const Microsoft::Windows::Foundation::decimal data{ -1234567890 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_decimal() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_decimal() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_bool) + { + const bool data{ true }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_bool() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_bool() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_char) + { + const char data{ -123 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_char() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_char() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_int16) + { + const std::int16_t data{ -32109}; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_int16() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_int16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_int32) + { + const std::int32_t data{ -1234567890 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_int32() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_int32() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_int64) + { + const std::int64_t data{ -1234567890123456789 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_int64() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_int64() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_uint8) + { + const std::uint8_t data{ 123 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_uint8() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_uint16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_uint16) + { + const std::uint16_t data{ 32109 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_uint16() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_uint16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_uint32) + { + const std::uint32_t data{ 1234567890 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_uint32() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_uint32() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_uint64) + { + const std::uint64_t data{ 0xFEDCBA0987654321 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_uint64() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_uint64() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_float) + { + const float data{ -1.25 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_float() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_float() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_double) + { + const double data{ -1.25 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_double() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_double() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_long) + { + const long data{ -1234567890 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_long() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_long() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_ulong) + { + const unsigned long data{ 1234567890 }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_ulong() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_ulong() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_pcwstr) + { + PCWSTR data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_string() }; + VERIFY_ARE_EQUAL(0, wcscmp(data, to.c_str())); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_string() }; + VERIFY_ARE_EQUAL(0, wcscmp(data, to.c_str()), std::format(L"'{}' == '{}'", data, to.c_str()).c_str()); + } + + TEST_METHOD(ctor_to_assign_pcwstr_lcid) + { + PCWSTR data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, GetSystemDefaultLCID()); + const auto to{ object.to_string(GetSystemDefaultLCID()) }; + VERIFY_ARE_EQUAL(0, wcscmp(data, to.c_str())); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_string(GetSystemDefaultLCID()) }; + VERIFY_ARE_EQUAL(0, wcscmp(data, to.c_str()), std::format(L"'{}' == '{}'", data, to.c_str()).c_str()); + } + + TEST_METHOD(ctor_to_assign_string) + { + const std::wstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_string() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_string() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_string_lcid_system_default) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_SYSTEM_DEFAULT); + const auto to{ object.to_hstring(LOCALE_SYSTEM_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_SYSTEM_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_string_lcid_user_default) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_USER_DEFAULT); + const auto to{ object.to_hstring(LOCALE_USER_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_USER_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_string_lcid_thread) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, GetThreadLocale()); + const auto to{ object.to_hstring(GetThreadLocale()) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(GetThreadLocale()) }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(ctor_to_assign_string_lcid_invariant) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_INVARIANT); + const auto to{ object.to_hstring(LOCALE_INVARIANT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_INVARIANT) }; + VERIFY_ARE_EQUAL(data, to2); + } + +#if defined(WINRT_BASE_H) + TEST_METHOD(ctor_to_assign_hstring) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data); + const auto to{ object.to_hstring() }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring() }; + VERIFY_ARE_EQUAL(data, to2); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + TEST_METHOD(ctor_to_assign_hstring_lcid_system_default) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_SYSTEM_DEFAULT); + const auto to{ object.to_hstring(LOCALE_SYSTEM_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_SYSTEM_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to2); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + TEST_METHOD(ctor_to_assign_hstring_lcid_user_default) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_USER_DEFAULT); + const auto to{ object.to_hstring(LOCALE_USER_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_USER_DEFAULT) }; + VERIFY_ARE_EQUAL(data, to2); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + TEST_METHOD(ctor_to_assign_hstring_lcid_thread) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, GetThreadLocale()); + const auto to{ object.to_hstring(GetThreadLocale()) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(GetThreadLocale()) }; + VERIFY_ARE_EQUAL(data, to2); + } +#endif // defined(WINRT_BASE_H) + +#if defined(WINRT_BASE_H) + TEST_METHOD(ctor_to_assign_hstring_lcid_invariant) + { + const winrt::hstring data{ L"-12.345" }; + const Microsoft::Windows::Foundation::decimal object(data, LOCALE_INVARIANT); + const auto to{ object.to_hstring(LOCALE_INVARIANT) }; + VERIFY_ARE_EQUAL(data, to); + + Microsoft::Windows::Foundation::decimal object2; + object2 = data; + const auto to2{ object.to_hstring(LOCALE_INVARIANT) }; + VERIFY_ARE_EQUAL(data, to2); + } +#endif // defined(WINRT_BASE_H) + + TEST_METHOD(compare_bool) + { + const Microsoft::Windows::Foundation::decimal decimal_false(false); + const Microsoft::Windows::Foundation::decimal decimal_true(true); + VERIFY_ARE_EQUAL(0, decimal_false.compare(decimal_false)); + VERIFY_ARE_EQUAL(0, decimal_true.compare(decimal_true)); + VERIFY_ARE_EQUAL(-1, decimal_false.compare(decimal_true)); + VERIFY_ARE_EQUAL(1, decimal_true.compare(decimal_false)); + + VERIFY_IS_TRUE(decimal_true == decimal_true); + VERIFY_IS_FALSE(decimal_true != decimal_true); + VERIFY_IS_FALSE(decimal_true < decimal_true); + VERIFY_IS_TRUE(decimal_true <= decimal_true); + VERIFY_IS_FALSE(decimal_true > decimal_true); + VERIFY_IS_TRUE(decimal_true >= decimal_true); + } + + TEST_METHOD(compare_char) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-123)); + const Microsoft::Windows::Foundation::decimal right(static_cast(123)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_int16) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-32109)); + const Microsoft::Windows::Foundation::decimal right(static_cast(32109)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_int32) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-1234567890)); + const Microsoft::Windows::Foundation::decimal right(static_cast(1234567890)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_int64) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-1234567890123456789)); + const Microsoft::Windows::Foundation::decimal right(static_cast(1234567890123456789)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint8) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(123)); + const Microsoft::Windows::Foundation::decimal right(static_cast(234)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint16) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(32109)); + const Microsoft::Windows::Foundation::decimal right(static_cast(65432)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint32) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(1234567890)); + const Microsoft::Windows::Foundation::decimal right(static_cast(4019283756)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint64) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(0x1234567890ABCDEF)); + const Microsoft::Windows::Foundation::decimal right(static_cast(0xFEDCBA0987654321)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_float) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-1.25)); + const Microsoft::Windows::Foundation::decimal right(static_cast(1.25)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_double) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-1.25)); + const Microsoft::Windows::Foundation::decimal right(static_cast(1.25)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_long) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(-1234567890)); + const Microsoft::Windows::Foundation::decimal right(static_cast(1234567890)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_ulong) + { + const Microsoft::Windows::Foundation::decimal left(static_cast(1234567890)); + const Microsoft::Windows::Foundation::decimal right(static_cast(4019283756)); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_string) + { + const Microsoft::Windows::Foundation::decimal left(L"-12.345"); + const Microsoft::Windows::Foundation::decimal right(L"12.345"); + VERIFY_ARE_EQUAL(0, left.compare(left)); + VERIFY_ARE_EQUAL(0, right.compare(right)); + VERIFY_ARE_EQUAL(-1, left.compare(right)); + VERIFY_ARE_EQUAL(1, right.compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_decimal) + { + const Microsoft::Windows::Foundation::decimal leftDecimal{ L"-12.345" }; + const DECIMAL left{ leftDecimal.to_decimal() }; + const Microsoft::Windows::Foundation::decimal rightDecimal{ L"12.345" }; + const DECIMAL right{ rightDecimal.to_decimal() }; + VERIFY_ARE_EQUAL(0, leftDecimal.compare(left)); + VERIFY_ARE_EQUAL(0, rightDecimal.compare(right)); + VERIFY_ARE_EQUAL(-1, leftDecimal.compare(right)); + VERIFY_ARE_EQUAL(1, rightDecimal.compare(left)); + + VERIFY_ARE_EQUAL(0, compare(left, left)); + VERIFY_ARE_EQUAL(0, compare(right, right)); + VERIFY_ARE_EQUAL(-1, compare(left, right)); + VERIFY_ARE_EQUAL(1, compare(right, left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(operator_pos) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + + const auto zero_value{ +zero }; + VERIFY_IS_TRUE(zero_value == zero); + VERIFY_IS_TRUE(zero_value != pos); + VERIFY_IS_TRUE(zero_value != neg); + VERIFY_IS_TRUE(zero_value < pos); + VERIFY_IS_TRUE(zero_value > neg); + + const auto pos_value{ +pos }; + VERIFY_IS_TRUE(pos_value != zero); + VERIFY_IS_TRUE(pos_value == pos); + VERIFY_IS_TRUE(pos_value != neg); + VERIFY_IS_TRUE(pos_value > zero); + VERIFY_IS_TRUE(pos_value > neg); + + const auto neg_value{ +neg }; + VERIFY_IS_TRUE(neg_value != zero); + VERIFY_IS_TRUE(neg_value != pos); + VERIFY_IS_TRUE(neg_value == neg); + VERIFY_IS_TRUE(neg_value < zero); + VERIFY_IS_TRUE(neg_value < pos); + } + + TEST_METHOD(scale) + { + const Microsoft::Windows::Foundation::decimal n_0{ L"79228162514264337593543950335" }; + VERIFY_ARE_EQUAL(0u, n_0.scale()); + + const Microsoft::Windows::Foundation::decimal n_1{ L"7922816251426433759354395033.5" }; + VERIFY_ARE_EQUAL(1u, n_1.scale()); + + const Microsoft::Windows::Foundation::decimal n_2{ L"792281625142643375935439503.35" }; + VERIFY_ARE_EQUAL(2u, n_2.scale()); + + const Microsoft::Windows::Foundation::decimal n_27{ L"79.228162514264337593543950335" }; + VERIFY_ARE_EQUAL(27u, n_27.scale()); + + const Microsoft::Windows::Foundation::decimal n_28{ L"7.9228162514264337593543950335" }; + VERIFY_ARE_EQUAL(28u, n_28.scale()); + + const Microsoft::Windows::Foundation::decimal neg_n_0{ L"-79228162514264337593543950335" }; + VERIFY_ARE_EQUAL(0u, neg_n_0.scale()); + + const Microsoft::Windows::Foundation::decimal neg_n_1{ L"-7922816251426433759354395033.5" }; + VERIFY_ARE_EQUAL(1u, neg_n_1.scale()); + + const Microsoft::Windows::Foundation::decimal neg_n_2{ L"-792281625142643375935439503.35" }; + VERIFY_ARE_EQUAL(2u, neg_n_2.scale()); + + const Microsoft::Windows::Foundation::decimal neg_n_27{ L"-79.228162514264337593543950335" }; + VERIFY_ARE_EQUAL(27u, neg_n_27.scale()); + + const Microsoft::Windows::Foundation::decimal neg_n_28{ L"-7.9228162514264337593543950335" }; + VERIFY_ARE_EQUAL(28u, neg_n_28.scale()); + } + + TEST_METHOD(sign) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + VERIFY_ARE_EQUAL(0, zero.sign()); + + const Microsoft::Windows::Foundation::decimal neg_zero(L"-0"); + VERIFY_ARE_EQUAL(0, neg_zero.sign()); + VERIFY_ARE_EQUAL(zero, neg_zero); + + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + VERIFY_ARE_EQUAL(1, pos.sign()); + + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + VERIFY_ARE_EQUAL(-1, neg.sign()); + } + + TEST_METHOD(min_max) + { + VERIFY_ARE_EQUAL(28u, Microsoft::Windows::Foundation::decimal::max_scale()); + + const Microsoft::Windows::Foundation::decimal max_decimal(L"79228162514264337593543950335"); + VERIFY_ARE_EQUAL(max_decimal, Microsoft::Windows::Foundation::decimal::max_value()); + + const Microsoft::Windows::Foundation::decimal min_decimal(L"-79228162514264337593543950335"); + VERIFY_ARE_EQUAL(min_decimal, Microsoft::Windows::Foundation::decimal::min_value()); + } + + TEST_METHOD(operator_neg) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + + const auto zero_value{ -zero }; + VERIFY_IS_TRUE(zero_value == zero); + VERIFY_IS_TRUE(zero_value != pos); + VERIFY_IS_TRUE(zero_value != neg); + VERIFY_IS_TRUE(zero_value < pos); + VERIFY_IS_TRUE(zero_value > neg); + + const auto pos_value{ -neg }; + VERIFY_IS_TRUE(pos_value != zero); + VERIFY_IS_TRUE(pos_value == pos); + VERIFY_IS_TRUE(pos_value != neg); + VERIFY_IS_TRUE(pos_value > zero); + VERIFY_IS_TRUE(pos_value > neg); + + const auto neg_value{ -pos }; + VERIFY_IS_TRUE(neg_value != zero); + VERIFY_IS_TRUE(neg_value != pos); + VERIFY_IS_TRUE(neg_value == neg); + VERIFY_IS_TRUE(neg_value < zero); + VERIFY_IS_TRUE(neg_value < pos); + } + + TEST_METHOD(abs) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + + const auto zero_value{ zero.abs() }; + VERIFY_IS_TRUE(zero_value == zero); + VERIFY_IS_TRUE(zero_value != pos); + VERIFY_IS_TRUE(zero_value != neg); + VERIFY_IS_TRUE(zero_value < pos); + VERIFY_IS_TRUE(zero_value > neg); + + const auto pos_value{ pos.abs() }; + VERIFY_IS_TRUE(pos_value != zero); + VERIFY_IS_TRUE(pos_value == pos); + VERIFY_IS_TRUE(pos_value != neg); + VERIFY_IS_TRUE(pos_value > zero); + VERIFY_IS_TRUE(pos_value > neg); + + const auto neg_value{ neg.abs() }; + VERIFY_IS_TRUE(neg_value != zero); + VERIFY_IS_TRUE(neg_value == pos); + VERIFY_IS_TRUE(neg_value != neg); + VERIFY_IS_TRUE(neg_value > zero); + VERIFY_IS_TRUE(neg_value == pos); + } + + TEST_METHOD(fix) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + const auto value{ zero.fix() }; + VERIFY_IS_TRUE(value == zero); + + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + const Microsoft::Windows::Foundation::decimal pos_fix(L"12"); + const auto pos_value{ pos.fix() }; + VERIFY_IS_TRUE(pos_value == pos_fix); + + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + const Microsoft::Windows::Foundation::decimal neg_fix(L"-12"); + const auto neg_value{ neg.fix() }; + VERIFY_IS_TRUE(neg_value == neg_fix); + } + + TEST_METHOD(integer) + { + const Microsoft::Windows::Foundation::decimal zero(L"0"); + const auto value{ zero.integer() }; + VERIFY_IS_TRUE(value == zero); + + const Microsoft::Windows::Foundation::decimal pos(L"12.345"); + const Microsoft::Windows::Foundation::decimal pos_integer(L"12"); + const auto pos_value{ pos.integer() }; + VERIFY_IS_TRUE(pos_value == pos_integer); + + const Microsoft::Windows::Foundation::decimal neg(L"-12.345"); + const Microsoft::Windows::Foundation::decimal neg_integer(L"-13"); + const auto neg_value{ neg.integer() }; + VERIFY_IS_TRUE(neg_value == neg_integer); + } + + TEST_METHOD(operator_increment) + { + struct values + { + PCWSTR left; + PCWSTR result; + } values[]{ + { L"0", L"1" }, + { L"1", L"2" }, + { L"123", L"124" }, + { L"255", L"256" }, + { L"65535", L"65536" }, + { L"1234567890", L"1234567891" }, + { L"91028374659102837465", L"91028374659102837466" }, + { L"-0", L"1" }, + { L"-1", L"0" }, + { L"-123", L"-122" }, + { L"-255", L"-254" }, + { L"-65535", L"-65534" }, + { L"-1234567890", L"-1234567889" }, + { L"-91028374659102837465", L"-91028374659102837464" }, + { L"1.2", L"2.2" }, + { L"-1.2", L"-0.2" }, + { L".2", L"1.2" }, + { L"-.2", L"0.8" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal before { value.left }; + Microsoft::Windows::Foundation::decimal expected{ value.result }; + { + Microsoft::Windows::Foundation::decimal left{ before }; + const Microsoft::Windows::Foundation::decimal returned{ ++left }; + VERIFY_ARE_EQUAL(returned, left, WEX::Common::String().Format(L"++%s value = %s vs %s", + before.to_string().c_str(), left.to_string().c_str(), expected.to_string().c_str())); + VERIFY_ARE_EQUAL(expected, left, WEX::Common::String().Format(L"++%s return = %s vs %s", + before.to_string().c_str(), returned.to_string().c_str(), expected.to_string().c_str())); + } + { + Microsoft::Windows::Foundation::decimal left{ before }; + const Microsoft::Windows::Foundation::decimal returned{ left++ }; + VERIFY_ARE_NOT_EQUAL(returned, left, WEX::Common::String().Format(L"%s++ value = %s vs %s", + before.to_string().c_str(), left.to_string().c_str(), expected.to_string().c_str())); + VERIFY_ARE_EQUAL(expected, left, WEX::Common::String().Format(L"%s++ return = %s vs %s", + before.to_string().c_str(), returned.to_string().c_str(), expected.to_string().c_str())); + } + } + } + + TEST_METHOD(operator_decrement) + { + struct values + { + PCWSTR left; + PCWSTR result; + } values[]{ + { L"0", L"-1" }, + { L"1", L"0" }, + { L"123", L"122" }, + { L"255", L"254" }, + { L"65535", L"65534" }, + { L"1234567890", L"1234567889" }, + { L"91028374659102837465", L"91028374659102837464" }, + { L"-0", L"-1" }, + { L"-1", L"-2" }, + { L"-123", L"-124" }, + { L"-255", L"-256" }, + { L"-65535", L"-65536" }, + { L"-1234567890", L"-1234567891" }, + { L"-91028374659102837465", L"-91028374659102837466" }, + { L"1.2", L"0.2" }, + { L"-1.2", L"-2.2" }, + { L".2", L"-0.8" }, + { L"-.2", L"-1.2" } + }; + for (size_t index=0; index < ARRAYSIZE(values); --index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal before { value.left }; + Microsoft::Windows::Foundation::decimal expected{ value.result }; + { + Microsoft::Windows::Foundation::decimal left{ before }; + const Microsoft::Windows::Foundation::decimal returned{ --left }; + VERIFY_ARE_EQUAL(returned, left, WEX::Common::String().Format(L"--%s value = %s vs %s", + before.to_string().c_str(), left.to_string().c_str(), expected.to_string().c_str())); + VERIFY_ARE_EQUAL(expected, left, WEX::Common::String().Format(L"--%s return = %s vs %s", + before.to_string().c_str(), returned.to_string().c_str(), expected.to_string().c_str())); + } + { + Microsoft::Windows::Foundation::decimal left{ before }; + const Microsoft::Windows::Foundation::decimal returned{ left-- }; + VERIFY_ARE_NOT_EQUAL(returned, left, WEX::Common::String().Format(L"%s-- value = %s vs %s", + before.to_string().c_str(), left.to_string().c_str(), expected.to_string().c_str())); + VERIFY_ARE_EQUAL(expected, left, WEX::Common::String().Format(L"%s-- return = %s vs %s", + before.to_string().c_str(), returned.to_string().c_str(), expected.to_string().c_str())); + } + } + } + + TEST_METHOD(operator_add) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"3" }, + { L"123", L"4567", L"4690" }, + { L"1", L"-2", L"-1" }, + { L"-1", L"-2", L"-3" }, + { L"-1", L"2", L"1" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"4.65" }, + { L"-1.2", L"3.45", L"2.25" }, + { L"1.2", L"-3.45", L"-2.25" }, + { L"-1.2", L"-3.45", L"-4.65" }, + { L".2", L".45", L".65" }, + { L"-.2", L".45", L".25" }, + { L".2", L"-.45", L"-.25" }, + { L"-.2", L"-.45", L"-.65" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal left{ value.left }; + const Microsoft::Windows::Foundation::decimal right{ value.right }; + const Microsoft::Windows::Foundation::decimal expected{ value.result }; + const Microsoft::Windows::Foundation::decimal result{ left + right }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s + %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result.to_string().c_str(), expected.to_string().c_str())); + + Microsoft::Windows::Foundation::decimal result2{ left }; + result2 += right; + VERIFY_ARE_EQUAL(expected, result2, WEX::Common::String().Format(L"%s += %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result2.to_string().c_str(), expected.to_string().c_str())); + } + } + + TEST_METHOD(operator_subtract) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"-1" }, + { L"123", L"4567", L"-4444" }, + { L"1", L"-2", L"3" }, + { L"-1", L"-2", L"1" }, + { L"-1", L"2", L"-3" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"-2.25" }, + { L"-1.2", L"3.45", L"-4.65" }, + { L"1.2", L"-3.45", L"4.65" }, + { L"-1.2", L"-3.45", L"2.25" }, + { L".2", L".45", L"-.25" }, + { L"-.2", L".45", L"-.65" }, + { L".2", L"-.45", L".65" }, + { L"-.2", L"-.45", L".25" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal left{ value.left }; + const Microsoft::Windows::Foundation::decimal right{ value.right }; + const Microsoft::Windows::Foundation::decimal expected{ value.result }; + const Microsoft::Windows::Foundation::decimal result{ left - right }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s - %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result.to_string().c_str(), expected.to_string().c_str())); + + Microsoft::Windows::Foundation::decimal result2{ left }; + result2 -= right; + VERIFY_ARE_EQUAL(expected, result2, WEX::Common::String().Format(L"%s -= %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result2.to_string().c_str(), expected.to_string().c_str())); + } + } + + TEST_METHOD(operator_multiply) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"2" }, + { L"123", L"4567", L"561741" }, + { L"1", L"-2", L"-2" }, + { L"-1", L"-2", L"2" }, + { L"-1", L"2", L"-2" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"4.140" }, + { L"-1.2", L"3.45", L"-4.140" }, + { L"1.2", L"-3.45", L"-4.140" }, + { L"-1.2", L"-3.45", L"4.140" }, + { L".2", L".45", L"0.090" }, + { L"-.2", L".45", L"-0.090" }, + { L".2", L"-.45", L"-0.090" }, + { L"-.2", L"-.45", L"0.090" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal left{ value.left }; + const Microsoft::Windows::Foundation::decimal right{ value.right }; + const Microsoft::Windows::Foundation::decimal expected{ value.result }; + const Microsoft::Windows::Foundation::decimal result{ left * right }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s * %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result.to_string().c_str(), expected.to_string().c_str())); + + Microsoft::Windows::Foundation::decimal result2{ left }; + result2 *= right; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s *= %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result2.to_string().c_str(), expected.to_string().c_str())); + } + } + + TEST_METHOD(operator_divide) + { + try + { + Microsoft::Windows::Foundation::decimal data{ 123 }; + Microsoft::Windows::Foundation::decimal zero{}; + const auto result{ data / zero }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (wil::ResultException& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.GetErrorCode(), WEX::Common::String().Format(L"0x%X %hs", e.GetErrorCode(), e.what())); + } + + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"1", L"2", L"0.5" }, + { L"123", L"4567", L"0.0269323407050580249616816291" }, + { L"1", L"-2", L"-0.5" }, + { L"-1", L"-2", L"0.5" }, + { L"-1", L"2", L"-0.5" }, + { L"1.2", L"3.45", L"0.3478260869565217391304347826" }, + { L"-1.2", L"3.45", L"-0.3478260869565217391304347826" }, + { L"1.2", L"-3.45", L"-0.3478260869565217391304347826" }, + { L"-1.2", L"-3.45", L"0.3478260869565217391304347826" }, + { L".2", L".45", L"0.4444444444444444444444444444" }, + { L"-.2", L".45", L"-0.4444444444444444444444444444" }, + { L".2", L"-.45", L"-0.4444444444444444444444444444" }, + { L"-.2", L"-.45", L"0.4444444444444444444444444444" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal left{ value.left }; + const Microsoft::Windows::Foundation::decimal right{ value.right }; + const Microsoft::Windows::Foundation::decimal expected{ value.result }; + const Microsoft::Windows::Foundation::decimal result{ left / right }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s / %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result.to_string().c_str(), expected.to_string().c_str())); + + Microsoft::Windows::Foundation::decimal result2{ left }; + result2 /= right; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s /= %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result2.to_string().c_str(), expected.to_string().c_str())); + } + } + + TEST_METHOD(operator_mod) + { + try + { + const Microsoft::Windows::Foundation::decimal data{ 123 }; + const Microsoft::Windows::Foundation::decimal zero{}; + const auto result{ data % zero }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (wil::ResultException& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.GetErrorCode(), WEX::Common::String().Format(L"0x%X %hs", e.GetErrorCode(), e.what())); + } + + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"1", L"2", L"1" }, + { L"123", L"4567", L"123" }, + { L"1", L"-2", L"1" }, + { L"-1", L"-2", L"-1" }, + { L"-1", L"2", L"-1" }, + { L"1.2", L"3.45", L"1.2" }, + { L"-1.2", L"3.45", L"-1.2" }, + { L"1.2", L"-3.45", L"1.2" }, + { L"-1.2", L"-3.45", L"-1.2" }, + { L".2", L".45", L"0.2" }, + { L"-.2", L".45", L"-0.2" }, + { L".2", L"-.45", L"0.2" }, + { L"-.2", L"-.45", L"-0.2" }, + + { L"2", L"1", L"0" }, + { L"4567", L"123", L"16" }, + { L"3.45", L"1.2", L"1.05" }, + { L"2", L"-1", L"0" }, + { L"-2", L"1", L"0" }, + { L"-2", L"-1", L"0" }, + { L"3.45", L"-1.2", L"1.05" }, + { L"-3.45", L"1.2", L"-1.05" }, + { L"-3.45", L"-1.2", L"-1.05" }, + { L".45", L".2", L"0.05" }, + { L".45", L"-.2", L"0.05" }, + { L"-.45", L".2", L"-0.05" }, + { L"-.45", L"-.2", L"-0.05" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const Microsoft::Windows::Foundation::decimal left{ value.left }; + const Microsoft::Windows::Foundation::decimal right{ value.right }; + const Microsoft::Windows::Foundation::decimal expected{ value.result }; + const Microsoft::Windows::Foundation::decimal result{ left % right }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s %% %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result.to_string().c_str(), expected.to_string().c_str())); + + Microsoft::Windows::Foundation::decimal result2{ left }; + result2 %= right; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s %%= %s = %s vs %s", + left.to_string().c_str(), right.to_string().c_str(), result2.to_string().c_str(), expected.to_string().c_str())); + } + } + + TEST_METHOD(operator_round) + { + const Microsoft::Windows::Foundation::decimal n_1_888{ L"1.888" }; + const Microsoft::Windows::Foundation::decimal n_neg1_888{ L"-1.888" }; + const Microsoft::Windows::Foundation::decimal n_1_25{ L"1.25" }; + const Microsoft::Windows::Foundation::decimal n_neg1_25{ L"-1.25" }; + + const Microsoft::Windows::Foundation::decimal n_2{ L"2" }; + const Microsoft::Windows::Foundation::decimal n_1_9{ L"1.9" }; + const Microsoft::Windows::Foundation::decimal n_1_89{ L"1.89" }; + const Microsoft::Windows::Foundation::decimal n_neg1_9{ L"1.9" }; + const Microsoft::Windows::Foundation::decimal n_neg1_89{ L"1.89" }; + + const Microsoft::Windows::Foundation::decimal n_1_888_round_0{ n_1_888.round(0) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.round(0) = %s vs %s", + n_1_888.to_string().c_str(), n_1_888_round_0.to_string().c_str(), n_2.to_string().c_str())); + + const Microsoft::Windows::Foundation::decimal n_1_888_round_1{ n_1_888.round(1) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.round(0) = %s vs %s", + n_1_888.to_string().c_str(), n_1_888_round_1.to_string().c_str(), n_1_9.to_string().c_str())); + + const Microsoft::Windows::Foundation::decimal n_1_888_round_2{ n_1_888.round(2) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.round(0) = %s vs %s", + n_1_888.to_string().c_str(), n_1_888_round_2.to_string().c_str(), n_1_89.to_string().c_str())); + + const Microsoft::Windows::Foundation::decimal n_1_888_round_3{ n_1_888.round(3) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.round(0) = %s vs %s", + n_1_888.to_string().c_str(), n_1_888_round_3.to_string().c_str(), n_1_888.to_string().c_str())); + + const Microsoft::Windows::Foundation::decimal n_1_888_round_4{ n_1_888.round(4) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.round(0) = %s vs %s", + n_1_888.to_string().c_str(), n_1_888_round_4.to_string().c_str(), n_1_888.to_string().c_str())); + } + }; +} diff --git a/test/Decimal/CPP/DecimalTests.vcxproj b/test/Decimal/CPP/DecimalTests.vcxproj new file mode 100644 index 0000000000..e5a6214b6b --- /dev/null +++ b/test/Decimal/CPP/DecimalTests.vcxproj @@ -0,0 +1,158 @@ + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + 16.0 + {4CBAF81E-F2F2-437c-BE4B-8F457DA572AA} + Win32Proj + DecimalTests + 10.0 + NativeUnitTestProject + DecimalTests + + + DynamicLibrary + false + v143 + Unicode + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + true + pch.h + $(RepoRoot)\test\inc;$(RepoRoot)\dev\common;$(VCInstallDir)UnitTest\include;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)\..\WindowsAppRuntime_BootstrapDLL;%(AdditionalIncludeDirectories) + $(RepoRoot);%(AdditionalIncludeDirectories) + + + Windows + onecore.lib;onecoreuap.lib;Microsoft.WindowsAppRuntime.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\WindowsAppRuntime_DLL + Microsoft.WindowsAppRuntime.Bootstrap.dll;%(DelayLoadDLLs) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + + Create + + + + + + + + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd + true + + + + + + + + {f76b776e-86f5-48c5-8fc7-d2795ecc9746} + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + diff --git a/test/Decimal/CPP/DecimalTests.vcxproj.filters b/test/Decimal/CPP/DecimalTests.vcxproj.filters new file mode 100644 index 0000000000..17872adfc2 --- /dev/null +++ b/test/Decimal/CPP/DecimalTests.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + + diff --git a/test/Decimal/CPP/Test.testdef b/test/Decimal/CPP/Test.testdef new file mode 100644 index 0000000000..579b2370ab --- /dev/null +++ b/test/Decimal/CPP/Test.testdef @@ -0,0 +1,11 @@ +{ + "Tests": [ + { + "Description": "C++ decimal tests", + "Filename": "DecimalTests.dll", + "Parameters": "", + "Architectures": ["x86", "x64", "arm64"], + "Status": "Enabled" + } + ] +} diff --git a/test/Decimal/CPP/packages.config b/test/Decimal/CPP/packages.config new file mode 100644 index 0000000000..0c13ff7b9c --- /dev/null +++ b/test/Decimal/CPP/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/Decimal/CPP/pch.cpp b/test/Decimal/CPP/pch.cpp new file mode 100644 index 0000000000..f59e66e263 --- /dev/null +++ b/test/Decimal/CPP/pch.cpp @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" diff --git a/test/Decimal/CPP/pch.h b/test/Decimal/CPP/pch.h new file mode 100644 index 0000000000..1d9596445a --- /dev/null +++ b/test/Decimal/CPP/pch.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef PCH_H +#define PCH_H + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#endif //PCH_H diff --git a/test/Decimal/CS/DecimalTest_CS.csproj b/test/Decimal/CS/DecimalTest_CS.csproj new file mode 100644 index 0000000000..d67992768a --- /dev/null +++ b/test/Decimal/CS/DecimalTest_CS.csproj @@ -0,0 +1,54 @@ + + + + Exe + net6.0-windows10.0.19041.0 + x86;x64;arm64 + disable + disable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + pdbonly + true + + + 1701;1702;1718 + + + 1701;1702;1718 + + + 1701;1702;1718 + + + 1701;1702;1718 + + + 1701;1702;1718 + + + 1701;1702;1718 + + + + + + + + + + + diff --git a/test/Decimal/CS/DotNetTests.cs b/test/Decimal/CS/DotNetTests.cs new file mode 100644 index 0000000000..cefbdb8964 --- /dev/null +++ b/test/Decimal/CS/DotNetTests.cs @@ -0,0 +1,660 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; +using Test; + +namespace Test.DotNet +{ + class DecimalTests + { + public static void Run() + { + ctor(); + ctor_to_assign_bool(); + ctor_to_assign_int16(); + ctor_to_assign_int32(); + ctor_to_assign_int64(); + ctor_to_assign_uint8(); + ctor_to_assign_uint16(); + ctor_to_assign_uint32(); + ctor_to_assign_uint64(); + ctor_to_assign_float(); + ctor_to_assign_double(); + ctor_to_assign_string(); + compare_int16(); + compare_int32(); + compare_int64(); + compare_uint8(); + compare_uint16(); + compare_uint32(); + compare_uint64(); + compare_float(); + compare_double(); + compare_string(); + operator_neg(); + abs(); + fix(); + integer(); + operator_add(); + operator_sub(); + operator_mul(); + operator_div(); + operator_mod(); + round(); + } + + public static void ctor() + { + var dec = new Decimal(); + var data = decimal.ToInt64(dec); + Verify.AreEqual(dec, data); + } + + public static void ctor_to_assign_bool() + { + bool data = true; + var dec = new Decimal(data ? 1 : 0); + var to = ((int)dec == 0) ? false : true; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_int16() + { + var data = (short)-123; + var dec = new Decimal(data); + var to = (short)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_int32() + { + var data = (int)-1234567890; + var dec = new Decimal(data); + var to = (int)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_int64() + { + var data = (long)-1234567890123456789; + var dec = new Decimal(data); + var to = (long)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_uint8() + { + var data = (byte)123; + var dec = new Decimal(data); + var to = (byte)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_uint16() + { + var data = (ushort)32109; + var dec = new Decimal(data); + var to = (ushort)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_uint32() + { + var data = (uint)1234567890; + var dec = new Decimal(data); + var to = (uint)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_uint64() + { + var data = (ulong)0xFEDCBA0987654321; + var dec = new Decimal(data); + var to = (ulong)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_float() + { + var data = (float)-1.25; + var dec = new Decimal(data); + var to = (float)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_double() + { + var data = (double)-1.25; + var dec = new Decimal(data); + var to = (double)dec; + Verify.AreEqual(data, to); + } + + public static void ctor_to_assign_string() + { + var data = "-12.345"; + var dec = Decimal.Parse(data); + var to = dec.ToString(); + Verify.AreEqual(data, to); + } + + public static void compare_int16() + { + var left = new Decimal((short)-32109); + var right = new Decimal((short)32109); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_int32() + { + var left = new Decimal((int)-1234567890); + var right = new Decimal((int)1234567890); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_int64() + { + var left = new Decimal((long)-1234567890123456789); + var right = new Decimal((long)1234567890123456789); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_uint8() + { + var left = new Decimal((byte)123); + var right = new Decimal((byte)234); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_uint16() + { + var left = new Decimal((ushort)32109); + var right = new Decimal((ushort)65432); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_uint32() + { + var left = new Decimal((uint)1234567890); + var right = new Decimal((uint)4019283756); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_uint64() + { + var left = new Decimal((ulong)0x1234567890ABCDEF); + var right = new Decimal((ulong)0xFEDCBA0987654321); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_float() + { + var left = new Decimal((float)-1.25); + var right = new Decimal((float)1.25); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_double() + { + var left = new Decimal((double)-1.25); + var right = new Decimal((double)1.25); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void compare_string() + { + var left = Decimal.Parse("-12.345"); + var right = Decimal.Parse("12.345"); + Verify.AreEqual(0, left.CompareTo(left)); + Verify.AreEqual(0, right.CompareTo(right)); + Verify.AreEqual(-1, left.CompareTo(right)); + Verify.AreEqual(1, right.CompareTo(left)); + + Verify.IsTrue(left == left); + Verify.IsFalse(left != left); + Verify.IsFalse(left < left); + Verify.IsTrue(left <= left); + Verify.IsFalse(left > left); + Verify.IsTrue(left >= left); + + Verify.IsTrue(right == right); + Verify.IsFalse(right != right); + Verify.IsFalse(right < right); + Verify.IsTrue(right <= right); + Verify.IsFalse(right > right); + Verify.IsTrue(right >= right); + + Verify.IsFalse(left == right); + Verify.IsTrue(left != right); + Verify.IsTrue(left < right); + Verify.IsTrue(left <= right); + Verify.IsFalse(left > right); + Verify.IsFalse(left >= right); + + Verify.IsFalse(right == left); + Verify.IsTrue(right != left); + Verify.IsFalse(right < left); + Verify.IsFalse(right <= left); + Verify.IsTrue(right > left); + Verify.IsTrue(right >= left); + } + + public static void operator_neg() + { + var zero = Decimal.Parse("0"); + var pos = Decimal.Parse("12.345"); + var neg = Decimal.Parse("-12.345"); + + var zero_value = -zero; + Verify.AreEqual(0, zero_value.CompareTo(zero)); + Verify.AreEqual(-1, zero_value.CompareTo(pos)); + Verify.AreEqual(1, zero_value.CompareTo(neg)); + + var pos_value = -neg; + Verify.AreEqual(1, pos_value.CompareTo(zero)); + Verify.AreEqual(0, pos_value.CompareTo(pos)); + Verify.AreEqual(1, pos_value.CompareTo(neg)); + + var neg_value = -pos; + Verify.AreEqual(-1, neg_value.CompareTo(zero)); + Verify.AreEqual(-1, neg_value.CompareTo(pos)); + Verify.AreEqual(0, neg_value.CompareTo(neg)); + } + + public static void abs() + { + var zero = Decimal.Parse("0"); + var pos = Decimal.Parse("12.345"); + var neg = Decimal.Parse("-12.345"); + + var zero_value = abs(zero); + Verify.AreEqual(0, zero_value.CompareTo(zero)); + Verify.AreEqual(-1, zero_value.CompareTo(pos)); + Verify.AreEqual(1, zero_value.CompareTo(neg)); + + var pos_value = abs(pos); + Verify.AreEqual(1, pos_value.CompareTo(zero)); + Verify.AreEqual(0, pos_value.CompareTo(pos)); + Verify.AreEqual(1, pos_value.CompareTo(neg)); + + var neg_value = abs(neg); + Verify.AreEqual(1, neg_value.CompareTo(zero)); + Verify.AreEqual(0, neg_value.CompareTo(pos)); + Verify.AreEqual(1, neg_value.CompareTo(neg)); + } + + public static void fix() + { + var zero = Decimal.Parse("0"); + var zero_value = (long)zero; + Verify.AreEqual(0, zero.CompareTo(zero_value)); + + var pos = Decimal.Parse("12.345"); + var pos_fix = Decimal.Parse("12"); + var pos_value = (long)pos; + Verify.AreEqual(0, pos_fix.CompareTo(pos_value)); + + var neg = Decimal.Parse("-12.345"); + var neg_fix = Decimal.Parse("-12"); + var neg_value = (long)neg; + Verify.AreEqual(0, neg_fix.CompareTo(neg_value)); + } + + public static void integer() + { + var zero = Decimal.Parse("0"); + var zero_value = (long)zero; + Verify.AreEqual(0, zero.CompareTo(zero_value)); + + var pos = Decimal.Parse("12.345"); + var pos_integer = Decimal.Parse("12"); + var pos_value = (long)pos; + Verify.AreEqual(0, pos_integer.CompareTo(pos_value)); + + var neg = Decimal.Parse("-12.345"); + var neg_integer = Decimal.Parse("-13"); + var neg_value = (long)neg; + if ((neg_value < 0) && (neg_value != neg)) + { + --neg_value; + } + Verify.AreEqual(0, neg_integer.CompareTo(neg_value)); + } + + public static void operator_add() + { + // TODO operator_add tests + } + + public static void operator_sub() + { + // TODO operator_sub tests + } + + public static void operator_mul() + { + // TODO operator_mul tests + } + + public static void operator_div() + { + // TODO operator_div tests + } + + public static void operator_mod() + { + // TODO operator_mod tests + } + + public static void round() + { + // TODO round tests + } + + private static Decimal abs(Decimal value) + { + var zero = new Decimal(0); + return value.CompareTo(zero) < 0 ? -value : value; + } + + public static void ToDecimal() + { + // TODO ToDecimal tests + } + + public static void ToDecimalValue() + { + // TODO ToDecimalValue tests + } + + public static void FromDecimal() + { + // TODO FromDecimal tests + } + + public static void FromDecimalValue() + { + // TODO FromDecimalValue tests + } + } +} diff --git a/test/Decimal/CS/Program.cs b/test/Decimal/CS/Program.cs new file mode 100644 index 0000000000..eb0b536b24 --- /dev/null +++ b/test/Decimal/CS/Program.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; +using Test.DotNet; +using Test.WinAppSDK; + +namespace Test +{ + class DecimalTests + { + static void Main(string[] args) + { + if (args.Length == 0) + { + Help(); + } + + var arg = args[0]; + if (arg.Equals("dotnet", StringComparison.OrdinalIgnoreCase)) + { + Test.DotNet.DecimalTests.Run(); + } + else if (arg.Equals("winappsdk", StringComparison.OrdinalIgnoreCase)) + { + Test.WinAppSDK.DecimalTests.Run(); + } + else + { + Help(); + } + } + + private static void Help() + { + Console.WriteLine("Usage: DecimalTest_CS \n" + + "where\n" + + " test = dotnet | winappsdk"); + Environment.Exit(1); + } + } +} diff --git a/test/Decimal/CS/Verify.cs b/test/Decimal/CS/Verify.cs new file mode 100644 index 0000000000..b54d5dbd50 --- /dev/null +++ b/test/Decimal/CS/Verify.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; + +namespace Test +{ + class Verify + { + public static bool IsTrue(bool value, string message = null) + { + if (value) + { + if (String.IsNullOrEmpty(message)) + { + Console.WriteLine($"Verify: IsTrue ({value})"); + } + else + { + Console.WriteLine($"ERROR: IsTrue ({value}) - {message}"); + } + } + else + { + if (String.IsNullOrEmpty(message)) + { + Console.WriteLine($"ERROR: IsTrue ({value})"); + } + else + { + Console.WriteLine($"ERROR: IsTrue({value}) - {message}"); + } + } + return value; + } + + public static bool IsFalse(bool value, string message = null) + { + if (!value) + { + if (String.IsNullOrEmpty(message)) + { + Console.WriteLine($"Verify: IsFalse ({value})"); + } + else + { + Console.WriteLine($"ERROR: IsFalse ({value}) - {message}"); + } + } + else + { + if (String.IsNullOrEmpty(message)) + { + Console.WriteLine($"ERROR: IsFalse ({value})"); + } + else + { + Console.WriteLine($"ERROR: IsFalse ({value}) - {message}"); + } + } + return !value; + } + + public static bool AreEqual(T left, T right, string message = null) + { + var ok = left.Equals(right); + if (ok) + { + Console.WriteLine($"Verify: AreEqual ({left}, {right})"); + } + else + { + if (String.IsNullOrEmpty(message)) + { + Console.WriteLine($"ERROR: Not equal ({left}, {right})"); + } + else + { + Console.WriteLine($"ERROR: Not equal ({left}, {right}) - {message}"); + } + } + return ok; + } + } +} diff --git a/test/Decimal/CS/WinAppSDKTests.cs b/test/Decimal/CS/WinAppSDKTests.cs new file mode 100644 index 0000000000..ef5dcb3a3d --- /dev/null +++ b/test/Decimal/CS/WinAppSDKTests.cs @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; + +namespace Test.WinAppSDK +{ + class DecimalTests + { + public static void Run() + { + ctor(); + ctor_to_assign_bool(); + ctor_to_assign_int16(); + ctor_to_assign_int32(); + ctor_to_assign_int64(); + ctor_to_assign_uint8(); + ctor_to_assign_uint16(); + ctor_to_assign_uint32(); + ctor_to_assign_uint64(); + ctor_to_assign_float(); + ctor_to_assign_double(); + ctor_to_assign_string(); + ctor_to_assign_string_locale_system(); + ctor_to_assign_string_locale_user(); + ctor_to_assign_string_locale_thread(); + ctor_to_assign_string_locale_invariant(); + compare_int16(); + compare_int32(); + compare_int64(); + compare_uint8(); + compare_uint16(); + compare_uint32(); + compare_uint64(); + compare_float(); + compare_double(); + compare_string(); + compare_string_locale_system(); + compare_string_locale_user(); + compare_string_locale_thread(); + compare_string_locale_invariant(); + operator_neg(); + abs(); + fix(); + integer(); + operator_add(); + operator_sub(); + operator_mul(); + operator_div(); + operator_mod(); + round(); + } + + private static void ctor() + { + //var decimal = new Microsoft.Windows.Foundation.Decimal(); + //var long data = decimal.to_int64(); + //Verify.AreEqual(0, dec.CompareTo(data); + } + + public static void ctor_to_assign_bool() + { + // TODO ctor_to_assign_bool tests + } + + public static void ctor_to_assign_int16() + { + // TODO ctor_to_assign_int16 tests + } + + public static void ctor_to_assign_int32() + { + // TODO ctor_to_assign_int32 tests + } + + public static void ctor_to_assign_int64() + { + // TODO ctor_to_assign_int64 tests + } + + public static void ctor_to_assign_uint8() + { + // TODO ctor_to_assign_uint8 tests + } + + public static void ctor_to_assign_uint16() + { + // TODO ctor_to_assign_uint16 tests + } + + public static void ctor_to_assign_uint32() + { + // TODO ctor_to_assign_uint32 tests + } + + public static void ctor_to_assign_uint64() + { + // TODO ctor_to_assign_uint64 tests + } + + public static void ctor_to_assign_float() + { + // TODO ctor_to_assign_float tests + } + + public static void ctor_to_assign_double() + { + // TODO ctor_to_assign_double tests + } + + public static void ctor_to_assign_string() + { + // TODO ctor_to_assign_string tests + } + + public static void ctor_to_assign_string_locale_system() + { + // TODO ctor_to_assign_string_locale_system tests + } + + public static void ctor_to_assign_string_locale_user() + { + // TODO ctor_to_assign_string_locale_user tests + } + + public static void ctor_to_assign_string_locale_thread() + { + // TODO ctor_to_assign_string_locale_thread tests + } + + public static void ctor_to_assign_string_locale_invariant() + { + // TODO ctor_to_assign_string_locale_invariant tests + } + + public static void compare_int16() + { + // TODO compare_int16 tests + } + + public static void compare_int32() + { + // TODO compare_int32 tests + } + + public static void compare_int64() + { + // TODO compare_int64 tests + } + + public static void compare_uint8() + { + // TODO compare_uint8 tests + } + + public static void compare_uint16() + { + // TODO compare_uint16 tests + } + + public static void compare_uint32() + { + // TODO compare_uint32 tests + } + + public static void compare_uint64() + { + // TODO compare_uint64 tests + } + + public static void compare_float() + { + // TODO compare_float tests + } + + public static void compare_double() + { + // TODO compare_double tests + } + + public static void compare_string() + { + // TODO compare_string tests + } + + public static void compare_string_locale_system() + { + // TODO compare_string_locale_system + } + + public static void compare_string_locale_user() + { + // TODO compare_string_locale_user + } + + public static void compare_string_locale_thread() + { + // TODO compare_string_locale_thread + } + + public static void compare_string_locale_invariant() + { + // TODO compare_string_locale_invariant + } + + public static void operator_neg() + { + // TODO operator_neg tests + } + + public static void abs() + { + // TODO abs tests + } + + public static void fix() + { + // TODO fix tests + } + + public static void integer() + { + // TODO integer tests + } + + public static void operator_add() + { + // TODO operator_add tests + } + + public static void operator_sub() + { + // TODO operator_sub tests + } + + public static void operator_mul() + { + // TODO operator_mul tests + } + + public static void operator_div() + { + // TODO operator_div tests + } + + public static void operator_mod() + { + // TODO operator_mod tests + } + + public static void round() + { + // TODO round tests + } + } +} diff --git a/test/Decimal/DecimalCalcuator/CS/DecimalCalculator_CS.csproj b/test/Decimal/DecimalCalcuator/CS/DecimalCalculator_CS.csproj new file mode 100644 index 0000000000..3a923c9cf6 --- /dev/null +++ b/test/Decimal/DecimalCalcuator/CS/DecimalCalculator_CS.csproj @@ -0,0 +1,36 @@ + + + + Exe + net6.0-windows10.0.19041.0 + x86;x64;arm64 + disable + disable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + pdbonly + true + + + + + + + + + + + diff --git a/test/Decimal/DecimalCalcuator/CS/Program.cs b/test/Decimal/DecimalCalcuator/CS/Program.cs new file mode 100644 index 0000000000..51ea956a55 --- /dev/null +++ b/test/Decimal/DecimalCalcuator/CS/Program.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +using System; + +namespace Microsoft.Windows.Foundation +{ + class DecimalCalculator + { + public static void Main(string[] args) + { + if (args.Length < 2) + { + Help(); + } + + string op = args[0]; + System.Decimal left = System.Decimal.Parse(args[1]); + System.Decimal right = (args.Length >= 3 ? System.Decimal.Parse(args[2]) : new System.Decimal(0)); + string expected = (args.Length >= 4 ? args[3] : null); + System.Decimal result = new System.Decimal(0); + if (args.Length == 3) + { + // NOTE: Decimal unary operators not supported by C#: ! ~ + switch (op) + { + case "+": result = +left; Output($"{op}{left} = {result}"); break; + case "-": result = -left; Output($"{op}{left} = {result}"); break; + case "++": result = ++left; Output($"{op}{left} = {result}"); break; + case "--": result = --left; Output($"{op}{left} = {result}"); break; + case "int32": expected = null; Console.WriteLine($"{op} {left} = {(int)left}"); break; + case "int64": expected = null; Console.WriteLine($"{op} {left} = {(long)left}"); break; + case "uint32": expected = null; Console.WriteLine($"{op} {left} = {(uint)left}"); break; + case "uint64": expected = null; Console.WriteLine($"{op} {left} = {(ulong)left}"); break; + case "float": expected = null; Console.WriteLine($"{op} {left} = {(float)left}"); break; + case "double": expected = null; Console.WriteLine($"{op} {left} = {(double)left}"); break; + default: UnknownOperator($"{op} {left}"); break; + } + } + else if (args.Length == 4) + { + // NOTE: Decimal unary operators not supported by C#: << >> >>> & | ^ + switch (op) + { + case "+": result = left + right; Output($"{left} {op} {right} = {result}"); break; + case "-": result = left - right; Output($"{left} {op} {right} = {result}"); break; + case "*": result = left * right; Output($"{left} {op} {right} = {result}"); break; + case "/": result = left / right; Output($"{left} {op} {right} = {result}"); break; + case "%": result = left % right; Output($"{left} {op} {right} = {result}"); break; + case "mod": result = left % right; Output($"{left} {op} {right} = {result}"); break; + case "==": expected = null; Console.WriteLine($"{left} {op} {right} = {left == right}"); break; + case "!=": expected = null; Console.WriteLine($"{left} {op} {right} = {left != right}"); break; + case "<": expected = null; Console.WriteLine($"{left} {op} {right} = {left < right}"); break; + case "<=": expected = null; Console.WriteLine($"{left} {op} {right} = {left <= right}"); break; + case ">": expected = null; Console.WriteLine($"{left} {op} {right} = {left > right}"); break; + case ">=": expected = null; Console.WriteLine($"{left} {op} {right} = {left >= right}"); break; + default: UnknownOperator($"{op} {left} {right}"); break; + } + } + else + { + Help(); + } + if (expected != null) + { + System.Decimal expectedValue = System.Decimal.Parse(expected); + Console.WriteLine($"==> {result} == {expectedValue} = {expectedValue == result}"); + } + } + + private static void Output(string evaluation) + { + Console.Write($"{evaluation,-32}"); + } + + private static void UnknownOperator(string message) + { + Console.WriteLine($"ERROR: Unknown operator {message}"); + Environment.Exit(2); + } + + private static void Help() + { + Console.WriteLine("Usage: DecimalCalculator_CS.exe []\n" + + "where\n" + + " operator = unary: + - ++ -- int32 int64 uint32 uint32 float double\n" + + " binary: + - * / % mod == != < <= > >=\n" + + " left = decimal value\n" + + " right = decimal value"); + Environment.Exit(1); + } + } +} diff --git a/test/Decimal/DecimalCalcuator/CS/py_test_mod.cmd b/test/Decimal/DecimalCalcuator/CS/py_test_mod.cmd new file mode 100644 index 0000000000..4fe2b969bb --- /dev/null +++ b/test/Decimal/DecimalCalcuator/CS/py_test_mod.cmd @@ -0,0 +1,42 @@ +@ECHO OFF +SETLOCAL + +IF %PYTHON_EXE%x == x GOTO NoPythonExe + +SET C=C:\Python313\python.exe -c + + +%C% "left=1 ; right=2 ; expected=1 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=123 ; right=4567 ; expected=123 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=1 ; right=-2 ; expected=1 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-1 ; right=-2 ; expected=-1 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-1 ; right=2 ; expected=-1 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=1.2 ; right=3.45 ; expected=1.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-1.2 ; right=3.45 ; expected=-1.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=1.2 ; right=-3.45 ; expected=1.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-1.2 ; right=-3.45 ; expected=-1.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=.2 ; right=.45 ; expected=0.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-.2 ; right=.45 ; expected=-0.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=.2 ; right=-.45 ; expected=0.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-.2 ; right=-.45 ; expected=-0.2 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=2 ; right=1 ; expected=0 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=4567 ; right=123 ; expected=16 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=3.45 ; right=1.2 ; expected=1.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=2 ; right=-1 ; expected=0 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-2 ; right=1 ; expected=0 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-2 ; right=-1 ; expected=0 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=3.45 ; right=-1.2 ; expected=1.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-3.45 ; right=1.2 ; expected=-1.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-3.45 ; right=-1.2 ; expected=-1.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=.45 ; right=.2 ; expected=0.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=.45 ; right=-.2 ; expected=0.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-.45 ; right=.2 ; expected=-0.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') +%C% "left=-.45 ; right=-.2 ; expected=-0.05 ; result=left %% right ; print(f'{left} %% {right} = {result}\t\t ==> {result} == {expected}\n') + +GOTO TheEnd + +:NoPythonExe +ECHO ERROR PYTHON_EXE environment variable not set + +:TheEnd +ENDLOCAL diff --git a/test/Decimal/DecimalCalcuator/CS/test_mod.cmd b/test/Decimal/DecimalCalcuator/CS/test_mod.cmd new file mode 100644 index 0000000000..a9ff1693f8 --- /dev/null +++ b/test/Decimal/DecimalCalcuator/CS/test_mod.cmd @@ -0,0 +1,35 @@ +@ECHO OFF +SETLOCAL + +SET C=DecimalCalculator_CS.exe + + +%C% mod 1 2 1 +%C% mod 123 4567 123 +%C% mod 1 -2 1 +%C% mod -1 -2 -1 +%C% mod -1 2 -1 +%C% mod 1.2 3.45 1.2 +%C% mod -1.2 3.45 -1.2 +%C% mod 1.2 -3.45 1.2 +%C% mod -1.2 -3.45 -1.2 +%C% mod .2 .45 0.2 +%C% mod -.2 .45 -0.2 +%C% mod .2 -.45 0.2 +%C% mod -.2 -.45 -0.2 +%C% mod 2 1 0 +%C% mod 4567 123 16 +%C% mod 3.45 1.2 1.05 +%C% mod 2 -1 0 +%C% mod -2 1 0 +%C% mod -2 -1 0 +%C% mod 3.45 -1.2 1.05 +%C% mod -3.45 1.2 -1.05 +%C% mod -3.45 -1.2 -1.05 +%C% mod .45 .2 0.05 +%C% mod .45 -.2 0.05 +%C% mod -.45 .2 -0.05 +%C% mod -.45 -.2 -0.05 + +:TheEnd +ENDLOCAL diff --git a/test/Decimal/WinRT/DecimalTest_WinRT.cpp b/test/Decimal/WinRT/DecimalTest_WinRT.cpp new file mode 100644 index 0000000000..7fe0057bbc --- /dev/null +++ b/test/Decimal/WinRT/DecimalTest_WinRT.cpp @@ -0,0 +1,1163 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include + +namespace TD = ::Test::Diagnostics; +namespace TB = ::Test::Bootstrap; +namespace TP = ::Test::Packages; +namespace TD = ::Test::Diagnostics; + +namespace WEX::TestExecution +{ + // Teach TAEF how to format a winrt::Microsoft::Windows::Foundation::Decimal + template <> + class VerifyOutputTraits + { + public: + static WEX::Common::NoThrowString ToString(winrt::Microsoft::Windows::Foundation::Decimal const& value) + { + const auto s{ value.ToString() }; + return WEX::Common::NoThrowString().Format(L"\"%s\"", s.c_str()); + } + }; + + // Teach TAEF how to compare a winrt::Microsoft::Windows::Foundation::Decimal + template <> + class VerifyCompareTraits + { + public: + static bool AreEqual(winrt::Microsoft::Windows::Foundation::Decimal const& expected, winrt::Microsoft::Windows::Foundation::Decimal const& actual) + { + return expected.Compare(actual) == 0; + } + + static bool AreSame(winrt::Microsoft::Windows::Foundation::Decimal const& expected, winrt::Microsoft::Windows::Foundation::Decimal const& actual) + { + return &expected == &actual; + } + + static bool IsLessThan(winrt::Microsoft::Windows::Foundation::Decimal const& expectedLess, winrt::Microsoft::Windows::Foundation::Decimal const& expectedGreater) + { + return expectedLess.Compare(expectedGreater) < 0; + } + + static bool IsGreaterThan(winrt::Microsoft::Windows::Foundation::Decimal const& expectedGreater, winrt::Microsoft::Windows::Foundation::Decimal const& expectedLess) + { + return expectedGreater.Compare(expectedLess) > 0; + } + + static bool IsNull(winrt::Microsoft::Windows::Foundation::Decimal const& object) + { + return !!object; + } + }; +} + +namespace Test::Decimal::Tests +{ + class DecimalTest_WinRT + { + public: + BEGIN_TEST_CLASS(DecimalTest_WinRT) + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + TEST_CLASS_PROPERTY(L"RunAs", L"RestrictedUser") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + ::TD::DumpExecutionContext(); + ::TB::Setup(TB::Packages::Framework); + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + ::TB::Cleanup(); + return true; + } + + TEST_METHOD(ctor) + { + const std::int64_t data{}; + winrt::Microsoft::Windows::Foundation::Decimal decimal; + const auto value{ decimal.ToInt64() }; + VERIFY_ARE_EQUAL(data, value); + } + + TEST_METHOD(create_to_set_decimal) + { + const std::int32_t dataValue{ -1234567890 }; + winrt::Microsoft::Windows::Foundation::Decimal data(winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(dataValue)); + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromDecimal(data) }; + const auto to{ object.ToDecimal() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromDecimal(data); + const auto to2{ object.ToDecimal() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_bool) + { + const bool data{ true }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromBoolean(data) }; + const auto to{ object.ToBoolean() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromBoolean(data); + const auto to2{ object.ToBoolean() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_int16) + { + const std::int16_t data{ -32109}; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt16(data) }; + const auto to{ object.ToInt16() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromInt16(data); + const auto to2{ object.ToInt16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_int32) + { + const std::int32_t data{ -1234567890 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(data) }; + const auto to{ object.ToInt32() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromInt32(data); + const auto to2{ object.ToInt32() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_int64) + { + const std::int64_t data{ -1234567890123456789 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt64(data) }; + const auto to{ object.ToInt64() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromInt64(data); + const auto to2{ object.ToInt64() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_uint8) + { + const std::uint8_t data{ 123 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt8(data) }; + const auto to{ object.ToUInt8() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromUInt8(data); + const auto to2{ object.ToUInt16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_uint16) + { + const std::uint16_t data{ 32109 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt16(data) }; + const auto to{ object.ToUInt16() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromUInt16(data); + const auto to2{ object.ToUInt16() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_uint32) + { + const std::uint32_t data{ 1234567890 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt32(data) }; + const auto to{ object.ToUInt32() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromUInt32(data); + const auto to2{ object.ToUInt32() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_uint64) + { + const std::uint64_t data{ 0xFEDCBA0987654321 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt64(data) }; + const auto to{ object.ToUInt64() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromUInt64(data); + const auto to2{ object.ToUInt64() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_single) + { + const float data{ -1.25 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromSingle(data) }; + const auto to{ object.ToSingle() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromSingle(data); + const auto to2{ object.ToSingle() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_double) + { + const double data{ -1.25 }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromDouble(data) }; + const auto to{ object.ToDouble() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromDouble(data); + const auto to2{ object.ToDouble() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_string) + { + const std::wstring data{ L"-12.345" }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(data) }; + const auto to{ object.ToString() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromString(data); + const auto to2{ object.ToString() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_string_locale_system_default) + { + const winrt::hstring data{ L"-12.345" }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromStringWithSystemDefaultLocale(data) }; + const auto to{ object.ToStringWithSystemDefaultLocale() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromStringWithSystemDefaultLocale(data); + const auto to2{ object.ToStringWithSystemDefaultLocale() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_string_locale_user_default) + { + const winrt::hstring data{ L"-12.345" }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromStringWithUserDefaultLocale(data) }; + const auto to{ object.ToStringWithUserDefaultLocale() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromStringWithUserDefaultLocale(data); + const auto to2{ object.ToStringWithUserDefaultLocale() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_string_locale_thread) + { + const winrt::hstring data{ L"-12.345" }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromStringWithThreadLocale(data) }; + const auto to{ object.ToStringWithThreadLocale() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromStringWithThreadLocale(data); + const auto to2{ object.ToStringWithThreadLocale() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(create_to_set_string_locale_invariant) + { + const winrt::hstring data{ L"-12.345" }; + winrt::Microsoft::Windows::Foundation::Decimal object{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromStringWithInvariantLocale(data) }; + const auto to{ object.ToStringWithInvariantLocale() }; + VERIFY_ARE_EQUAL(data, to); + + winrt::Microsoft::Windows::Foundation::Decimal object2; + object2.SetFromStringWithInvariantLocale(data); + const auto to2{ object.ToStringWithInvariantLocale() }; + VERIFY_ARE_EQUAL(data, to2); + } + + TEST_METHOD(compare_bool) + { + winrt::Microsoft::Windows::Foundation::Decimal decimal_false{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromBoolean(false) }; + winrt::Microsoft::Windows::Foundation::Decimal decimal_true{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromBoolean(true) }; + VERIFY_ARE_EQUAL(0, decimal_false.Compare(decimal_false)); + VERIFY_ARE_EQUAL(0, decimal_true.Compare(decimal_true)); + VERIFY_ARE_EQUAL(-1, decimal_false.Compare(decimal_true)); + VERIFY_ARE_EQUAL(1, decimal_true.Compare(decimal_false)); + + VERIFY_IS_TRUE(decimal_true == decimal_true); + VERIFY_IS_FALSE(decimal_true != decimal_true); + VERIFY_IS_FALSE(decimal_true < decimal_true); + VERIFY_IS_TRUE(decimal_true <= decimal_true); + VERIFY_IS_FALSE(decimal_true > decimal_true); + VERIFY_IS_TRUE(decimal_true >= decimal_true); + } + + TEST_METHOD(compare_int16) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt16(static_cast(-32109)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt16(static_cast(32109)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_int32) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(static_cast(-1234567890)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(static_cast(1234567890)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_int64) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt64(static_cast(-1234567890123456789)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt64(static_cast(1234567890123456789)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint8) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt8(static_cast(123)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt8(static_cast(234)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint16) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt16(static_cast(32109)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt16(static_cast(65432)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint32) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt32(static_cast(1234567890)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt32(static_cast(4019283756)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_uint64) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt64(static_cast(0x1234567890ABCDEF)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromUInt64(static_cast(0xFEDCBA0987654321)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_float) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromSingle(static_cast(-1.25)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromSingle(static_cast(1.25)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_double) + { + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromDouble(static_cast(-1.25)) }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromDouble(static_cast(1.25)) }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_string) + { + const winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"-12.345") }; + const winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"12.345") }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(compare_decimal) + { + const winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"-12.345") }; + const winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"12.345") }; + VERIFY_ARE_EQUAL(0, left.Compare(left)); + VERIFY_ARE_EQUAL(0, right.Compare(right)); + VERIFY_ARE_EQUAL(-1, left.Compare(right)); + VERIFY_ARE_EQUAL(1, right.Compare(left)); + + VERIFY_IS_TRUE(left == left); + VERIFY_IS_FALSE(left != left); + VERIFY_IS_FALSE(left < left); + VERIFY_IS_TRUE(left <= left); + VERIFY_IS_FALSE(left > left); + VERIFY_IS_TRUE(left >= left); + + VERIFY_IS_TRUE(right == right); + VERIFY_IS_FALSE(right != right); + VERIFY_IS_FALSE(right < right); + VERIFY_IS_TRUE(right <= right); + VERIFY_IS_FALSE(right > right); + VERIFY_IS_TRUE(right >= right); + + VERIFY_IS_FALSE(left == right); + VERIFY_IS_TRUE(left != right); + VERIFY_IS_TRUE(left < right); + VERIFY_IS_TRUE(left <= right); + VERIFY_IS_FALSE(left > right); + VERIFY_IS_FALSE(left >= right); + + VERIFY_IS_FALSE(right == left); + VERIFY_IS_TRUE(right != left); + VERIFY_IS_FALSE(right < left); + VERIFY_IS_FALSE(right <= left); + VERIFY_IS_TRUE(right > left); + VERIFY_IS_TRUE(right >= left); + } + + TEST_METHOD(scale) + { + const auto n_0{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"79228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(0u, n_0.Scale()); + + const auto n_1{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"7922816251426433759354395033.5" }) }; + VERIFY_ARE_EQUAL(1u, n_1.Scale()); + + const auto n_2{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"792281625142643375935439503.35" }) }; + VERIFY_ARE_EQUAL(2u, n_2.Scale()); + + const auto n_27{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"79.228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(27u, n_27.Scale()); + + const auto n_28{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"7.9228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(28u, n_28.Scale()); + + const auto neg_n_0{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-79228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(0u, neg_n_0.Scale()); + + const auto neg_n_1{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-7922816251426433759354395033.5" }) }; + VERIFY_ARE_EQUAL(1u, neg_n_1.Scale()); + + const auto neg_n_2{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-792281625142643375935439503.35" }) }; + VERIFY_ARE_EQUAL(2u, neg_n_2.Scale()); + + const auto neg_n_27{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-79.228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(27u, neg_n_27.Scale()); + + const auto neg_n_28{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-7.9228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(28u, neg_n_28.Scale()); + } + + TEST_METHOD(sign) + { + const winrt::Microsoft::Windows::Foundation::Decimal zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"0" }) }; + VERIFY_ARE_EQUAL(0, zero.Sign()); + + const winrt::Microsoft::Windows::Foundation::Decimal neg_zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-0" }) }; + VERIFY_ARE_EQUAL(0, neg_zero.Sign()); + VERIFY_ARE_EQUAL(zero, neg_zero); + + const winrt::Microsoft::Windows::Foundation::Decimal pos{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12.345" }) }; + VERIFY_ARE_EQUAL(1, pos.Sign()); + + const winrt::Microsoft::Windows::Foundation::Decimal neg{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12.345" }) }; + VERIFY_ARE_EQUAL(-1, neg.Sign()); + } + + TEST_METHOD(min_max) + { + VERIFY_ARE_EQUAL(28u, winrt::Microsoft::Windows::Foundation::Decimal::MaxScale()); + + const winrt::Microsoft::Windows::Foundation::Decimal max_decimal{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"79228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(max_decimal, winrt::Microsoft::Windows::Foundation::Decimal::MaxValue()); + + const winrt::Microsoft::Windows::Foundation::Decimal min_decimal{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-79228162514264337593543950335" }) }; + VERIFY_ARE_EQUAL(min_decimal, winrt::Microsoft::Windows::Foundation::Decimal::MinValue()); + } + + TEST_METHOD(negate) + { + winrt::Microsoft::Windows::Foundation::Decimal zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"0" }) }; + winrt::Microsoft::Windows::Foundation::Decimal pos{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal neg{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12.345" }) }; + + const auto zero_value{ zero.Negate() }; + VERIFY_IS_TRUE(zero_value == zero); + VERIFY_IS_TRUE(zero_value != pos); + VERIFY_IS_TRUE(zero_value != neg); + VERIFY_IS_TRUE(zero_value < pos); + VERIFY_IS_TRUE(zero_value > neg); + + const auto pos_value{ neg.Negate() }; + VERIFY_IS_TRUE(pos_value != zero); + VERIFY_IS_TRUE(pos_value == pos); + VERIFY_IS_TRUE(pos_value != neg); + VERIFY_IS_TRUE(pos_value > zero); + VERIFY_IS_TRUE(pos_value > neg); + + const auto neg_value{ pos.Negate() }; + VERIFY_IS_TRUE(neg_value != zero); + VERIFY_IS_TRUE(neg_value != pos); + VERIFY_IS_TRUE(neg_value == neg); + VERIFY_IS_TRUE(neg_value < zero); + VERIFY_IS_TRUE(neg_value < pos); + } + + TEST_METHOD(abs) + { + winrt::Microsoft::Windows::Foundation::Decimal zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"0" }) }; + winrt::Microsoft::Windows::Foundation::Decimal pos{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal neg{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12.345" }) }; + + const auto zero_value{ zero.Abs() }; + VERIFY_IS_TRUE(zero_value == zero); + VERIFY_IS_TRUE(zero_value != pos); + VERIFY_IS_TRUE(zero_value != neg); + VERIFY_IS_TRUE(zero_value < pos); + VERIFY_IS_TRUE(zero_value > neg); + + const auto pos_value{ pos.Abs() }; + VERIFY_IS_TRUE(pos_value != zero); + VERIFY_IS_TRUE(pos_value == pos); + VERIFY_IS_TRUE(pos_value != neg); + VERIFY_IS_TRUE(pos_value > zero); + VERIFY_IS_TRUE(pos_value > neg); + + const auto neg_value{ neg.Abs() }; + VERIFY_IS_TRUE(neg_value != zero); + VERIFY_IS_TRUE(neg_value == pos); + VERIFY_IS_TRUE(neg_value != neg); + VERIFY_IS_TRUE(neg_value > zero); + VERIFY_IS_TRUE(neg_value == pos); + } + + TEST_METHOD(fix) + { + winrt::Microsoft::Windows::Foundation::Decimal zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"0" }) }; + const auto value{ zero.Fix() }; + VERIFY_IS_TRUE(value == zero); + + winrt::Microsoft::Windows::Foundation::Decimal pos{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal pos_fix{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12" }) }; + const auto pos_value{ pos.Fix() }; + VERIFY_IS_TRUE(pos_value == pos_fix); + + winrt::Microsoft::Windows::Foundation::Decimal neg{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal neg_fix{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12" }) }; + const auto neg_value{ neg.Fix() }; + VERIFY_IS_TRUE(neg_value == neg_fix); + } + + TEST_METHOD(integer) + { + winrt::Microsoft::Windows::Foundation::Decimal zero{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"0" }) }; + const auto value{ zero.Integer() }; + VERIFY_IS_TRUE(value == zero); + + winrt::Microsoft::Windows::Foundation::Decimal pos{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal pos_integer{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"12" }) }; + const auto pos_value{ pos.Integer() }; + VERIFY_IS_TRUE(pos_value == pos_integer); + + winrt::Microsoft::Windows::Foundation::Decimal neg{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-12.345" }) }; + winrt::Microsoft::Windows::Foundation::Decimal neg_integer{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(winrt::hstring{ L"-13" }) }; + const auto neg_value{ neg.Integer() }; + VERIFY_IS_TRUE(neg_value == neg_integer); + } + + TEST_METHOD(operator_add) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"3" }, + { L"123", L"4567", L"4690" }, + { L"1", L"-2", L"-1" }, + { L"-1", L"-2", L"-3" }, + { L"-1", L"2", L"1" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"4.65" }, + { L"-1.2", L"3.45", L"2.25" }, + { L"1.2", L"-3.45", L"-2.25" }, + { L"-1.2", L"-3.45", L"-4.65" }, + { L".2", L".45", L".65" }, + { L"-.2", L".45", L".25" }, + { L".2", L"-.45", L"-.25" }, + { L"-.2", L"-.45", L"-.65" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const winrt::hstring leftString{ value.left }; + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(leftString) }; + const winrt::hstring rightString{ value.right }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(rightString) }; + const winrt::hstring expectedString{ value.result }; + winrt::Microsoft::Windows::Foundation::Decimal expected{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(expectedString) }; + const winrt::Microsoft::Windows::Foundation::Decimal result{ left.Add(right) }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s Add %s = %s vs %s", + left.ToString().c_str(), right.ToString().c_str(), result.ToString().c_str(), expected.ToString().c_str())); + } + } + + TEST_METHOD(operator_subtract) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"-1" }, + { L"123", L"4567", L"-4444" }, + { L"1", L"-2", L"3" }, + { L"-1", L"-2", L"1" }, + { L"-1", L"2", L"-3" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"-2.25" }, + { L"-1.2", L"3.45", L"-4.65" }, + { L"1.2", L"-3.45", L"4.65" }, + { L"-1.2", L"-3.45", L"2.25" }, + { L".2", L".45", L"-.25" }, + { L"-.2", L".45", L"-.65" }, + { L".2", L"-.45", L".65" }, + { L"-.2", L"-.45", L".25" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const winrt::hstring leftString{ value.left }; + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(leftString) }; + const winrt::hstring rightString{ value.right }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(rightString) }; + const winrt::hstring expectedString{ value.result }; + winrt::Microsoft::Windows::Foundation::Decimal expected{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(expectedString) }; + const winrt::Microsoft::Windows::Foundation::Decimal result{ left.Sub(right) }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s Sub %s = %s vs %s", + left.ToString().c_str(), right.ToString().c_str(), result.ToString().c_str(), expected.ToString().c_str())); + } + } + + TEST_METHOD(operator_multiply) + { + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"0", L"0", L"0" }, + { L"1", L"2", L"2" }, + { L"123", L"4567", L"561741" }, + { L"1", L"-2", L"-2" }, + { L"-1", L"-2", L"2" }, + { L"-1", L"2", L"-2" }, + { L"-0", L"-0", L"0" }, + { L"-0", L"0", L"0" }, + { L"0", L"-0", L"0" }, + { L"1.2", L"3.45", L"4.140" }, + { L"-1.2", L"3.45", L"-4.140" }, + { L"1.2", L"-3.45", L"-4.140" }, + { L"-1.2", L"-3.45", L"4.140" }, + { L".2", L".45", L"0.090" }, + { L"-.2", L".45", L"-0.090" }, + { L".2", L"-.45", L"-0.090" }, + { L"-.2", L"-.45", L"0.090" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const winrt::hstring leftString{ value.left }; + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(leftString) }; + const winrt::hstring rightString{ value.right }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(rightString) }; + const winrt::hstring expectedString{ value.result }; + winrt::Microsoft::Windows::Foundation::Decimal expected{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(expectedString) }; + const winrt::Microsoft::Windows::Foundation::Decimal result{ left.Mul(right) }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s Mul %s = %s vs %s", + left.ToString().c_str(), right.ToString().c_str(), result.ToString().c_str(), expected.ToString().c_str())); + } + } + + TEST_METHOD(operator_divide) + { + try + { + winrt::Microsoft::Windows::Foundation::Decimal data{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(123) }; + winrt::Microsoft::Windows::Foundation::Decimal zero{}; + const auto result{ data.Div(zero) }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (wil::ResultException& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.GetErrorCode(), WEX::Common::String().Format(L"0x%X %hs", e.GetErrorCode(), e.what())); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.code(), WEX::Common::String().Format(L"0x%X %hs", e.code(), e.message().c_str())); + } + + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"1", L"2", L"0.5" }, + { L"123", L"4567", L"0.0269323407050580249616816291" }, + { L"1", L"-2", L"-0.5" }, + { L"-1", L"-2", L"0.5" }, + { L"-1", L"2", L"-0.5" }, + { L"1.2", L"3.45", L"0.3478260869565217391304347826" }, + { L"-1.2", L"3.45", L"-0.3478260869565217391304347826" }, + { L"1.2", L"-3.45", L"-0.3478260869565217391304347826" }, + { L"-1.2", L"-3.45", L"0.3478260869565217391304347826" }, + { L".2", L".45", L"0.4444444444444444444444444444" }, + { L"-.2", L".45", L"-0.4444444444444444444444444444" }, + { L".2", L"-.45", L"-0.4444444444444444444444444444" }, + { L"-.2", L"-.45", L"0.4444444444444444444444444444" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const winrt::hstring leftString{ value.left }; + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(leftString) }; + const winrt::hstring rightString{ value.right }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(rightString) }; + const winrt::hstring expectedString{ value.result }; + winrt::Microsoft::Windows::Foundation::Decimal expected{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(expectedString) }; + const winrt::Microsoft::Windows::Foundation::Decimal result{ left.Div(right) }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s Div %s = %s vs %s", + left.ToString().c_str(), right.ToString().c_str(), result.ToString().c_str(), expected.ToString().c_str())); + } + } + + TEST_METHOD(operator_mod) + { + try + { + winrt::Microsoft::Windows::Foundation::Decimal data{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromInt32(123) }; + winrt::Microsoft::Windows::Foundation::Decimal zero{}; + const auto result{ data.Mod(zero) }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (wil::ResultException& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.GetErrorCode(), WEX::Common::String().Format(L"0x%X %hs", e.GetErrorCode(), e.what())); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(DISP_E_DIVBYZERO, e.code(), WEX::Common::String().Format(L"0x%X %hs", e.code(), e.message().c_str())); + } + + struct values + { + PCWSTR left; + PCWSTR right; + PCWSTR result; + } values[]{ + { L"1", L"2", L"1" }, + { L"123", L"4567", L"123" }, + { L"1", L"-2", L"1" }, + { L"-1", L"-2", L"-1" }, + { L"-1", L"2", L"-1" }, + { L"1.2", L"3.45", L"1.2" }, + { L"-1.2", L"3.45", L"-1.2" }, + { L"1.2", L"-3.45", L"1.2" }, + { L"-1.2", L"-3.45", L"-1.2" }, + { L".2", L".45", L"0.2" }, + { L"-.2", L".45", L"-0.2" }, + { L".2", L"-.45", L"0.2" }, + { L"-.2", L"-.45", L"-0.2" }, + + { L"2", L"1", L"0" }, + { L"4567", L"123", L"16" }, + { L"3.45", L"1.2", L"1.05" }, + { L"2", L"-1", L"0" }, + { L"-2", L"1", L"0" }, + { L"-2", L"-1", L"0" }, + { L"3.45", L"-1.2", L"1.05" }, + { L"-3.45", L"1.2", L"-1.05" }, + { L"-3.45", L"-1.2", L"-1.05" }, + { L".45", L".2", L"0.05" }, + { L".45", L"-.2", L"0.05" }, + { L"-.45", L".2", L"-0.05" }, + { L"-.45", L"-.2", L"-0.05" } + }; + for (size_t index=0; index < ARRAYSIZE(values); ++index) + { + const auto& value{ values[index] }; + const winrt::hstring leftString{ value.left }; + winrt::Microsoft::Windows::Foundation::Decimal left{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(leftString) }; + const winrt::hstring rightString{ value.right }; + winrt::Microsoft::Windows::Foundation::Decimal right{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(rightString) }; + const winrt::hstring expectedString{ value.result }; + winrt::Microsoft::Windows::Foundation::Decimal expected{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(expectedString) }; + const winrt::Microsoft::Windows::Foundation::Decimal result{ left.Mod(right) }; + VERIFY_ARE_EQUAL(expected, result, WEX::Common::String().Format(L"%s Mod %s = %s vs %s", + left.ToString().c_str(), right.ToString().c_str(), result.ToString().c_str(), expected.ToString().c_str())); + } + } + + TEST_METHOD(operator_round) + { + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.888") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_neg1_888{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"-1.888") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_1_25{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.25") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_neg1_25{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"-1.25") }; + + const winrt::Microsoft::Windows::Foundation::Decimal n_2{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"2") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_1_9{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.9") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_1_89{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.89") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_neg1_9{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.9") }; + const winrt::Microsoft::Windows::Foundation::Decimal n_neg1_89{ winrt::Microsoft::Windows::Foundation::Decimal::CreateFromString(L"1.89") }; + + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888_round_0{ n_1_888.Round(0) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.Round(0) = %s vs %s", + n_1_888.ToString().c_str(), n_1_888_round_0.ToString().c_str(), n_2.ToString().c_str())); + + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888_round_1{ n_1_888.Round(1) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.Round(0) = %s vs %s", + n_1_888.ToString().c_str(), n_1_888_round_1.ToString().c_str(), n_1_9.ToString().c_str())); + + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888_round_2{ n_1_888.Round(2) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.Round(0) = %s vs %s", + n_1_888.ToString().c_str(), n_1_888_round_2.ToString().c_str(), n_1_89.ToString().c_str())); + + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888_round_3{ n_1_888.Round(3) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.Round(0) = %s vs %s", + n_1_888.ToString().c_str(), n_1_888_round_3.ToString().c_str(), n_1_888.ToString().c_str())); + + const winrt::Microsoft::Windows::Foundation::Decimal n_1_888_round_4{ n_1_888.Round(4) }; + VERIFY_ARE_EQUAL(n_2, n_1_888_round_0, WEX::Common::String().Format(L"%s.Round(0) = %s vs %s", + n_1_888.ToString().c_str(), n_1_888_round_4.ToString().c_str(), n_1_888.ToString().c_str())); + } + }; +} diff --git a/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj b/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj new file mode 100644 index 0000000000..318a5e480c --- /dev/null +++ b/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj @@ -0,0 +1,167 @@ + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + 16.0 + {E9C055BB-6AE4-497a-A354-D07841E68976} + Win32Proj + DecimalTest_WinRT + 10.0 + NativeUnitTestProject + DecimalTest_WinRT + + + DynamicLibrary + false + v143 + Unicode + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + true + pch.h + $(RepoRoot)\test\inc;$(RepoRoot)\dev\common;$(VCInstallDir)UnitTest\include;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)\..\WindowsAppRuntime_BootstrapDLL;%(AdditionalIncludeDirectories) + $(RepoRoot);%(AdditionalIncludeDirectories) + + + Windows + onecore.lib;onecoreuap.lib;Microsoft.WindowsAppRuntime.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\WindowsAppRuntime_DLL + Microsoft.WindowsAppRuntime.Bootstrap.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + + Create + + + + + + + + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.Foundation.winmd + true + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd + true + + + + + + + + {f76b776e-86f5-48c5-8fc7-d2795ecc9746} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + + diff --git a/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj.filters b/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj.filters new file mode 100644 index 0000000000..0cb73aeaad --- /dev/null +++ b/test/Decimal/WinRT/DecimalTest_WinRT.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + + diff --git a/test/Decimal/WinRT/Test.testdef b/test/Decimal/WinRT/Test.testdef new file mode 100644 index 0000000000..1958bbc7c3 --- /dev/null +++ b/test/Decimal/WinRT/Test.testdef @@ -0,0 +1,11 @@ +{ + "Tests": [ + { + "Description": "WinRT Decimal tests", + "Filename": "DecimalTest_WinRT.dll", + "Parameters": "", + "Architectures": ["x86", "x64", "arm64"], + "Status": "Enabled" + } + ] +} diff --git a/test/Decimal/WinRT/packages.config b/test/Decimal/WinRT/packages.config new file mode 100644 index 0000000000..0c13ff7b9c --- /dev/null +++ b/test/Decimal/WinRT/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/Decimal/WinRT/pch.cpp b/test/Decimal/WinRT/pch.cpp new file mode 100644 index 0000000000..f59e66e263 --- /dev/null +++ b/test/Decimal/WinRT/pch.cpp @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" diff --git a/test/Decimal/WinRT/pch.h b/test/Decimal/WinRT/pch.h new file mode 100644 index 0000000000..1d9596445a --- /dev/null +++ b/test/Decimal/WinRT/pch.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef PCH_H +#define PCH_H + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#endif //PCH_H diff --git a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml index 7666d7f656..ddd0772a2a 100644 --- a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml +++ b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml @@ -116,6 +116,12 @@ + + + Microsoft.WindowsAppRuntime.dll + + + Microsoft.WindowsAppRuntime.dll diff --git a/test/inc/WindowsAppRuntime.Test.Bootstrap.h b/test/inc/WindowsAppRuntime.Test.Bootstrap.h index 11ca387114..a831f77aa0 100644 --- a/test/inc/WindowsAppRuntime.Test.Bootstrap.h +++ b/test/inc/WindowsAppRuntime.Test.Bootstrap.h @@ -158,16 +158,16 @@ namespace Test::Bootstrap s_bootstrapDll.reset(); } - inline void Setup() + inline void Setup(Test::Bootstrap::Packages packagesToSetup = Test::Bootstrap::Packages::Default) { - SetupPackages(); + SetupPackages(packagesToSetup); SetupBootstrap(); } - inline void Cleanup() + inline void Cleanup(Test::Bootstrap::Packages packagesToSetup = Test::Bootstrap::Packages::Default) { CleanupBootstrap(); - CleanupPackages(); + CleanupPackages(packagesToSetup); } } diff --git a/test/inc/WindowsAppRuntime.Test.Diagnostics.h b/test/inc/WindowsAppRuntime.Test.Diagnostics.h index 9d546c3510..54c766fb53 100644 --- a/test/inc/WindowsAppRuntime.Test.Diagnostics.h +++ b/test/inc/WindowsAppRuntime.Test.Diagnostics.h @@ -7,6 +7,7 @@ #include #include +#include #include diff --git a/tools/VerifyCopyrightHeaders.ps1 b/tools/VerifyCopyrightHeaders.ps1 index a974ecabdd..a9e42048ae 100644 --- a/tools/VerifyCopyrightHeaders.ps1 +++ b/tools/VerifyCopyrightHeaders.ps1 @@ -22,7 +22,7 @@ $copyrightHeaderText = ( ) $include = ('*.cs', '*.cpp', '*.h', '*.idl', '*.xaml') -$exclude = [RegEx]'\\dev\\Detours\\|\\BuildOutput\\|\\obj\\|\\localpackages\\|\\packages\\|\\specs\\|\\temp\\|\\Debug\\|\\Release\\|\\ItemTemplates\\|\\ProjectTemplates\\|\\WindowsAppSDKAggregator\\' +$exclude = [RegEx]'\\dev\\Detours\\|\\BuildOutput\\|\\obj\\|\\localpackages\\|\\packages\\|\\Packages\\|\\specs\\|\\temp\\|\\Debug\\|\\Release\\|\\ItemTemplates\\|\\ProjectTemplates\\|\\WindowsAppSDKAggregator\\' $files = dir $PSScriptRoot\..\* -recurse -include $include | Where FullName -notmatch $exclude $errorCount = 0