From 0351199b235c4d9bc55eeb5f9f1aa045b4afc341 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Sun, 11 May 2025 10:32:27 -0700
Subject: [PATCH 01/10] Decimal spec

---
 specs/decimal/decimal.md | 467 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 467 insertions(+)
 create mode 100644 specs/decimal/decimal.md

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
new file mode 100644
index 0000000000..d0f05b378f
--- /dev/null
+++ b/specs/decimal/decimal.md
@@ -0,0 +1,467 @@
+# 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{};
+
+    /// WinRT representation of the Win32 DECIMAL structure.
+    /// @note This is the identical memory layout and encoding of the Win32 DECIMAL structure.
+    ///       The latter's definition is valid for COM but not WinRT making this equivalent structure necessary.
+    /// @see https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1
+    [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 DecimalHelper
+    {
+        static DecimalValue FromBoolean(Boolean value);
+        static DecimalValue FromInt16(Int16 value);
+        static DecimalValue FromInt32(Int32 value);
+        static DecimalValue FromInt64(Int64 value);
+        static DecimalValue FromUInt8(UInt8 value);
+        static DecimalValue FromUInt16(UInt16 value);
+        static DecimalValue FromUInt32(UInt32 value);
+        static DecimalValue FromUInt64(UInt64 value);
+        static DecimalValue FromSingle(Single value);
+        static DecimalValue FromDouble(Double value);
+        static DecimalValue FromString(String value);                          // LCID=LOCALE_INVARIANT
+        static DecimalValue FromStringWithSystemDefaultLocale(String value);   // LCID=GetSystemDefaultLCID()
+        static DecimalValue FromStringWithUserDefaultLocale(String value);     // LCID=GetUserDefaultLCID()
+        static DecimalValue FromStringWithThreadLocale(String value);          // LCID=GetThreadLocale()
+
+        static Boolean ToBoolean(DecimalValue value);
+        static Int16 ToInt16(DecimalValue value);
+        static Int32 ToInt32(DecimalValue value);
+        static Int64 ToInt64(DecimalValue value);
+        static UInt8 ToUInt8(DecimalValue value);
+        static UInt16 ToUInt16(DecimalValue value);
+        static UInt32 ToUInt32(DecimalValue value);
+        static UInt64 ToUInt64(DecimalValue value);
+        static Single ToSingle(DecimalValue value);
+        static Double ToDouble(DecimalValue value);
+        static String ToString(DecimalValue value);                         // LCID=LOCALE_INVARIANT
+        static String ToStringWithSystemDefaultLocale(DecimalValue value);  // LCID=GetSystemDefaultLCID()
+        static String ToStringWithUserDefaultLocale(DecimalValue value);    // LCID=GetUserDefaultLCID()
+        static String ToStringWithThreadLocale(DecimalValue value);         // LCID=GetThreadLocale()
+
+        /// Return true if (left == right).
+        static Boolean Equals(DecimalValue left, DecimalValue right);
+
+        /// Compare decimal values.
+        /// @return 0 if left and right are equal, <0 if left is less than right or >0 if left is greater than right.
+        static Int32 Compare(DecimalValue left, DecimalValue right);
+
+        /// Return true if the value is valid.
+        static Boolean IsValid(DecimalValue value);
+
+        /// Return the scaling factor of the value (the number of decimal digits).
+        /// @return the scaling factor, ranging from 0 to max_scale().
+        static UInt32 Scale(DecimalValue value);
+
+        /// Return the sign of the value.
+        /// @return 0 if value is zero, <0 if value is less than zero or >0 if value is greater than zero.
+        static Int32 Sign(DecimalValue value);
+
+        /// Return the maximum scaling factor
+        static UInt32 MaxScale();
+
+        /// Return the maximum value (79,228,162,514,264,337,593,543,950,335).
+        static DecimalValue MaxValue();
+
+        /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335).
+        static DecimalValue MinValue();
+
+        /// Return a decimal whose value is (-value).
+        static DecimalValue Negate(DecimalValue value);
+
+        /// Return the absolute value.
+        static DecimalValue Abs(DecimalValue value);
+
+        /// Return the integral digits; any fractional digits are discarded.
+        static DecimalValue Truncate(DecimalValue value);
+
+        /// Return the integral digits rounded down to -infinity; any fractional digits are discarded.
+        static DecimalValue Floor(DecimalValue value);
+
+        /// Return the integral digits rounded up to +infinity; any fractional digits are discarded.
+        static DecimalValue Ceiling(DecimalValue value);
+
+        /// Return the value rounded to the specific number of decimal places.
+        static DecimalValue Round(DecimalValue value, Int32 decimalPlaces);
+
+        /// Return value clamped to the inclusive range of min and max.
+        /// @return value if min <= value <= max, or min if value < min, or max if max < value.
+        static DecimalValue Clamp(DecimalValue value, DecimalValue min, DecimalValue max);
+
+        /// Returns a DecimalValue whose value is (left + right).
+        static DecimalValue Add(DecimalValue left, DecimalValue right);
+
+        /// Returns a DecimalValue whose value is (left - right).
+        static DecimalValue Subtract(DecimalValue left, DecimalValue right);
+
+        /// Returns a DecimalValue whose value is (left * right).
+        static DecimalValue Multiply(DecimalValue left, DecimalValue right);
+
+        /// Returns a DecimalValue whose value is (left / right).
+        static DecimalValue Divide(DecimalValue left, DecimalValue right);
+
+        /// Returns a DecimalValue whose value is (left % right).
+        static DecimalValue Modulo(DecimalValue left, DecimalValue right);
+    }
+}
+```
+
+# 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()` `truncate()` `floor()` `ceil()` `round()` `clamp()`
+* 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. decimal.h
+
+```c++
+#if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
+#define __WindowsAppSDK_Microsoft_Windows_Foundation_decimal_
+
+#include <oleauto.h>
+
+#if !defined(_VC_NODEFAULTLIB)
+#pragma comment(linker, "/defaultlib:oleaut32.lib")
+#endif
+
+inline int compare(const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator==(const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator!=(const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator< (const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator<=(const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator> (const DECIMAL& left, const DECIMAL& right);
+
+inline bool operator>=(const DECIMAL& left, const DECIMAL& right);
+
+namespace Microsoft::Windows::Foundation
+{
+class decimal
+{
+public:
+    decimal() = default;
+    ~decimal() = default;
+
+    decimal(const decimal& value);
+    decimal(decimal&& value);
+    constexpr decimal(const DECIMAL& value);
+    decimal(bool value)l
+    decimal(char value);
+    decimal(std::int16_t value);
+    decimal(std::int32_t value);
+    decimal(std::int64_t value);
+    decimal(std::uint8_t value);
+    decimal(std::uint16_t value);
+    decimal(std::uint32_t value);
+    decimal(std::uint64_t value);
+    decimal(float value);
+    decimal(double value);
+    decimal(long value);
+    decimal(unsigned long value);
+    decimal(PCWSTR value);
+    decimal(PCWSTR value, const LCID locale);
+    decimal(const std::wstring& value);
+    decimal(const std::wstring& value, const LCID locale);
+#if defined(__WINSTRING_H_)
+    decimal(const HSTRING& value);
+    decimal(const HSTRING& value, const LCID locale);
+#endif // defined(__WINSTRING_H_)
+#if defined(WINRT_BASE_H)
+    decimal(const winrt::hstring& value);
+    decimal(const winrt::hstring& value, const LCID locale);
+#endif // defined(WINRT_BASE_H)
+
+    decimal& operator=(const decimal& value);
+    decimal& operator=(decimal&& value);
+    decimal& operator=(const DECIMAL& value);
+    decimal& operator=(bool value);
+    decimal& operator=(char value);
+    decimal& operator=(std::int16_t value);
+    decimal& operator=(std::int32_t value);
+    decimal& operator=(std::int64_t value);
+    decimal& operator=(std::uint8_t value);
+    decimal& operator=(std::uint16_t value);
+    decimal& operator=(std::uint32_t value);
+    decimal& operator=(std::uint64_t value);
+    decimal& operator=(float value);
+    decimal& operator=(double value);
+    decimal& operator=(long value);
+    decimal& operator=(unsigned long value);
+    decimal& operator=(PCWSTR value);
+    decimal& operator=(const std::wstring& value);
+#if defined(__WINSTRING_H_)
+    decimal& operator=(const HSTRING& value);
+#endif // defined(__WINSTRING_H_)
+#if defined(WINRT_BASE_H)
+    decimal& operator=(const winrt::hstring& value);
+#endif // defined(WINRT_BASE_H)
+
+    const DECIMAL& to_decimal() const;
+    bool to_bool() const;
+    char to_char() const;
+    std::int16_t to_int16() const;
+    std::int32_t to_int32() const;
+    std::int64_t to_int64() const;
+    std::uint8_t to_uint8() const;
+    std::uint16_t to_uint16() const;
+    std::uint32_t to_uint32() const;
+    std::uint64_t to_uint64() const;
+    float to_float() const;
+    double to_double() const;
+    long to_long() const;
+    unsigned long to_ulong() const;
+    std::wstring to_string() const;
+    std::wstring to_string(const LCID locale) const;
+#if defined(__WINSTRING_H_)
+    HSTRING to_HSTRING() const;
+    HSTRING to_HSTRING(const LCID locale) const;
+#endif // defined(WINRT_BASE_H)
+#if defined(WINRT_BASE_H)
+    winrt::hstring to_hstring() const;
+    winrt::hstring to_hstring(const LCID locale) const;
+#endif // defined(WINRT_BASE_H)
+
+    bool operator==(const decimal& value) const;
+    bool operator!=(const decimal& value) const;
+    bool operator< (const decimal& value) const;
+    bool operator<=(const decimal& value) const;
+    bool operator> (const decimal& value) const;
+    bool operator>=(const decimal& value) const;
+    int compare(const decimal& value) const;
+
+    bool operator==(const DECIMAL& value) const;
+    bool operator!=(const DECIMAL& value) const;
+    bool operator< (const DECIMAL& value) const;
+    bool operator<=(const DECIMAL& value) const;
+    bool operator> (const DECIMAL& value) const;
+    bool operator>=(const DECIMAL& value) const;
+    int compare(const DECIMAL& value) const;
+
+    /// Return true if this is valid.
+    bool is_valid();
+
+    /// Return true if value is valid.
+    static constexpr bool is_valid(const 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 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 the maximum scaling factor
+    static constexpr std::uint32_t max_scale();
+
+    /// Return the maximum value (79,228,162,514,264,337,593,543,950,335).
+    static constexpr decimal max_value();
+
+    /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335).
+    static constexpr decimal min_value();
+
+    decimal operator+() const;
+
+    decimal operator-() const;
+
+    decimal abs() const;
+
+    /// Return the integral digits; any fractional digits are discarded.
+    decimal truncate() const;
+
+    /// Return the integral digits rounded down to -infinity; any fractional digits are discarded.
+    decimal floor() const;
+
+    /// Return the integral digits rounded up to +infinity; any fractional digits are discarded.
+    decimal ceil() const;
+
+    /// Return this clamped to the inclusive range of min and max.
+    /// @return this if min <= this <= max, or min if this < min, or max if max < this.
+    decimal clamp(decimal min, decimal max) const;
+
+    decimal operator++();
+    decimal operator++(int);
+
+    decimal operator--();
+    decimal operator--(int);
+
+    decimal operator+(const decimal& value) const;
+    decimal operator-(const decimal& value) const;
+    decimal operator*(const decimal& value) const;
+    decimal operator/(const decimal& value) const;
+
+    /// 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;
+
+    decimal& operator+=(const decimal& value);
+    decimal& operator-=(const decimal& value);
+    decimal& operator*=(const decimal& value);
+    decimal& operator/=(const decimal& value);
+    decimal& operator%=(const decimal& value);
+
+    decimal round(const std::int32_t decimalPlaces) const;
+
+private:
+    DECIMAL m_decimal{};
+};
+}
+
+#endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
+```
+
+## 4.2. decimalcppwinmrt.h
+
+```c++
+// Copyright (c) Microsoft Corporation and Contributors.
+// Licensed under the MIT License.
+
+#include <oleauto.h>
+
+//----------------------------------------------------------------------
+// WinRT DecimalValue support
+
+#if defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_)
+#define __WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_
+
+//----------------------------------------------------------
+// WinRT DecimalValue <-> Win32 DECIMAL conversions
+
+namespace winrt::Microsoft::Windows::Foundation
+{
+/// Return value as a Win32 DECIMAL structure.
+inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+
+/// Return value as a WinRT DecimalValue structure.
+inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value);
+}
+
+//----------------------------------------------------------
+// WinRT DecimalValue operators
+
+// C++/WinRT generates bool operator==(DecimalValue const& left, DecimalValue const& right)
+
+// C++/WinRT generates bool operator!=(DecimalValue const& left, DecimalValue const& right)
+
+inline bool operator<(
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+
+inline bool operator<=(
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+
+inline bool operator>(
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+
+inline bool operator>=(
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+
+#endif // defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_)
+
+//----------------------------------------------------------------------
+// C++ decimal support
+
+#if defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)
+#define __WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_
+
+//----------------------------------------------------------
+// WinRT DecimalValue <-> C++ decimal conversions
+
+namespace winrt::Microsoft::Windows::Foundation
+{
+/// Return true if value is valid.
+constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+
+/// Return value as a C++ decimal object.
+inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+
+/// Return value as a WinRT DecimalValue structure.
+inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value);
+}
+
+#endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)
+```

From 23387a19d4cb0c719e088db9c7093a24326001db Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 12 May 2025 19:11:42 -0700
Subject: [PATCH 02/10] Added examples

---
 specs/decimal/decimal.md | 149 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 2 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index d0f05b378f..0cff83f2fd 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -45,7 +45,152 @@ data structure may be re-expressed in each language using language-specific cons
 defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with
 WinRT IDL.
 
-# 3. WinRT API
+# 3. Examples
+
+The examples are a program displaying the results of the the mathematical formula:
+
+```
+x = (((a - b) + (c % d)) * e).round(5) / f;
+y = x++.round(3).clamp(f, g);
+z = --y.floor() * ++x.ceil() * -y.truncate();
+```
+
+Given the values
+
+```
+a = 1
+b = 0.5
+c = -6.66
+d = 1.23
+e = 4567.089
+f = -4
+g = 1967
+h = 1001.0
+```
+
+the output is
+
+```
+x == 12.4177225
+y == 11.418
+z == -1540
+```
+
+and the process exit code is -1540.
+
+# 3.1. C#
+
+NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal)
+providing the canonical reference for examples in other languages.
+
+```c++
+Using System;
+Using System.IO;
+
+class Program
+{
+    static void Main()
+    {
+        var a = new Decimal(1);
+        var b = new Decimal(0.5);
+        var c = Decimal.Parse("-6.66");
+        var d = Decimal.Parse("1.23");
+        var e = Decimal.Parse("4567.089");
+        var f = new Decimal((long)-4);
+        var g = new Decimal((uint)1967);
+        var h = new Decimal(1001.0);
+
+        var x = Decimal.Round(((a - b) + (c % d)) * e, 5) / f;
+        var y = Math.Clamp(Decimal.Round(x++, 3), f, g);
+        var yfloor = Decimal.Floor(y);
+        var xceil = Decimal.Ceiling(x);
+        var z = --yfloor * ++xceil * -Decimal.Truncate(y);
+
+        Console.WriteLine($"x = {x}");
+        Console.WriteLine($"y = {y}");
+        Console.WriteLine($"z = {z}");
+
+        Environment.Exit((int)z);
+    }
+}
+```
+
+# 3.2. C++
+
+This program illustrates the reference example using Windows App SDK's C++ decimal class.
+
+```c++
+#include <windows.h>
+#include <stdio.h>
+#include <decimal.h>
+
+int main()
+{
+    const Microsoft::Windows::Foundation::decimal a{ 1 };
+    const Microsoft::Windows::Foundation::decimal b{ 0.5 };
+    const Microsoft::Windows::Foundation::decimal c{ L"-6.66" };
+    const Microsoft::Windows::Foundation::decimal d{ L"1.23" };
+    const Microsoft::Windows::Foundation::decimal e{ L"4567.089" };
+    const Microsoft::Windows::Foundation::decimal f{ -4ll };
+    const Microsoft::Windows::Foundation::decimal g{ 1967u };
+    const Microsoft::Windows::Foundation::decimal h{ 1001.0f };
+
+    auto x = (((a - b) + (c % d)) * e).round(5) / f;
+    auto y = x++.round(3).clamp(f, g);
+    auto z = --y.floor() * ++x.ceil() * -y.truncate();
+
+    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"x = %ls", x.to_string().c_str()));
+    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"y = %ls", y.to_string().c_str()));
+    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"z = %ls", z.to_string().c_str()));
+
+    printf(L"x = %ls\n", x.to_string().c_str());
+    printf(L"y = %ls\n", y.to_string().c_str());
+    printf(L"z = %ls\n", z.to_string().c_str());
+    return z.to_int32();
+}
+```
+
+# 3.3. WinRT
+
+This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass.
+
+```c++
+#include <windows.h>
+#include <stdio.h>
+#include <winrt/Microsoft.Windows.Foundation.h>
+
+int main()
+{
+    using DH = winrt::Microsoft::Windows::Foundation::DecimalHelper;
+    const auto a{ DH::FromInt32(1) };
+    const auto b{ DH::FromDouble(0.5) };
+    const auto c{ DH::FromString(L"-6.66") };
+    const auto d{ DH::FromString(L"1.23") };
+    const auto e{ DH::FromString(L"4567.089") };
+    const auto f{ DH::FromInt64(-4ll) };
+    const auto g{ DH::FromUInt16(1967u) };
+    const auto h{ DH::FromSingle(1001.0f) };
+
+    // WinRT equivalent to C++ formula
+    //
+    //   x = (((a - b) + (c % d)) * e).round(5) / f
+    //   y = x++.round(3).clamp(f, g)
+    //   z = --y.floor() * ++x.ceil() * -y.truncate()
+
+    auto x = DH::Divide(DH::Round(DH::Multiply(DH::Add(DH::Subtract(a, b), (DH::Modulo(c, d))), e), 5), f);
+    auto one = DH::FromInt32(1);
+    auto y = DH::Clamp(DH::Round(x, 3), f, g);
+    x = DH::Add(x, one);
+    auto z = DH::Multiply(DH::Multiply(DH::Subtract(DH::Floor(y), one), DH::Add(DH::Ceiling(x), one)), DH::Negate(DH::Truncate(y)));
+
+    printf(L"x = %ls\n", DH::ToString(x).c_str());
+    printf(L"y = %ls\n", DH::ToString(y).c_str());
+    printf(L"z = %ls\n", DH::ToString(z).c_str());
+    return DH::ToInt32(z);
+}
+```
+
+# 4. WinRT API
 
 Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure.
 
@@ -171,7 +316,7 @@ namespace Microsoft.Windows.Foundation
 }
 ```
 
-# 4. C++ API
+# 5. 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:

From 1e32d6d07b1bb5640e0c4abb4c1b442ad59dd48c Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Tue, 13 May 2025 11:59:54 -0700
Subject: [PATCH 03/10] Added TOC. Added C# API. Fixed some numbering

---
 specs/decimal/decimal.md | 47 ++++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 0cff83f2fd..2906a928d6 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -1,3 +1,15 @@
+- [1. Decimal](#1-decimal)
+- [2. Common Decimal Representation](#2-common-decimal-representation)
+- [3. Examples](#3-examples)
+- [4. C#](#4-c)
+- [5. C++](#5-c)
+- [6. WinRT](#6-winrt)
+- [7. WinRT API](#7-winrt-api)
+- [8. C++ API](#8-c-api)
+  - [8.1. decimal.h](#81-decimalh)
+  - [8.2. decimalcppwinmrt.h](#82-decimalcppwinmrth)
+- [9. C# API](#9-c-api)
+
 # 1. Decimal
 
 THIS FEATURE IS CURRENTLY EXPERIMENTAL.
@@ -78,7 +90,7 @@ z == -1540
 
 and the process exit code is -1540.
 
-# 3.1. C#
+# 4. C#
 
 NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal)
 providing the canonical reference for examples in other languages.
@@ -115,7 +127,7 @@ class Program
 }
 ```
 
-# 3.2. C++
+# 5. C++
 
 This program illustrates the reference example using Windows App SDK's C++ decimal class.
 
@@ -150,7 +162,7 @@ int main()
 }
 ```
 
-# 3.3. WinRT
+# 6. WinRT
 
 This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass.
 
@@ -190,7 +202,7 @@ int main()
 }
 ```
 
-# 4. WinRT API
+# 7. WinRT API
 
 Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure.
 
@@ -316,7 +328,7 @@ namespace Microsoft.Windows.Foundation
 }
 ```
 
-# 5. C++ API
+# 8. 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:
@@ -332,7 +344,7 @@ Windows App SDK provides a native language decimal data type for C++ as the
 
 Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception
 
-## 4.1. decimal.h
+## 8.1. decimal.h
 
 ```c++
 #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
@@ -536,7 +548,9 @@ private:
 #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
 ```
 
-## 4.2. decimalcppwinmrt.h
+## 8.2. decimalcppwinmrt.h
+
+This header provides C++/WinRT and Windows App SDK's DecimalValue integration.
 
 ```c++
 // Copyright (c) Microsoft Corporation and Contributors.
@@ -610,3 +624,22 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic
 
 #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)
 ```
+
+# 9. C# API
+
+C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal).
+Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`.
+
+```c#
+namespace Microsoft.Windows.Foundation
+{
+    public static class DecimalExtensions
+    {
+        /// Return a WinRT DecimalValue structure.
+        public static Microsoft.Windows.Foundation.DecimalValue ToDecimalValue(this decimal d);
+
+        /// Return a C# Decimal object.
+        public static decimal FromDecimalValue(this decimal d, Microsoft.Windows.Foundation.DecimalValue value);
+    }
+}
+```

From 96444b098141afa55f26b9242883268bda226326 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 26 May 2025 11:49:22 -0700
Subject: [PATCH 04/10] Incorporate feedback

---
 specs/decimal/decimal.md | 251 +++++++++++++++++++++++++++++----------
 1 file changed, 189 insertions(+), 62 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 2906a928d6..994524e530 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -7,7 +7,7 @@
 - [7. WinRT API](#7-winrt-api)
 - [8. C++ API](#8-c-api)
   - [8.1. decimal.h](#81-decimalh)
-  - [8.2. decimalcppwinmrt.h](#82-decimalcppwinmrth)
+  - [8.2. decimalcppwinmrt.h](#82-decimalcppwinrth)
 - [9. C# API](#9-c-api)
 
 # 1. Decimal
@@ -57,6 +57,13 @@ data structure may be re-expressed in each language using language-specific cons
 defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with
 WinRT IDL.
 
+2.1. OLE Automation APIs
+
+The [OLE Automation APIs](https://learn.microsoft.com/windows/win32/api/oleauto/) operating on
+[DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) provide the
+core functionality used by the APIs in this spec e.g. [VarDecFromStr](https://learn.microsoft.com/windows/win32/api/oleauto/nf-oleauto-vardecfromstr)
+to convert a string to `DECIMAL`.
+
 # 3. Examples
 
 The examples are a program displaying the results of the the mathematical formula:
@@ -90,7 +97,7 @@ z == -1540
 
 and the process exit code is -1540.
 
-# 4. C#
+# 3.1. C# Example
 
 NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal)
 providing the canonical reference for examples in other languages.
@@ -114,9 +121,7 @@ class Program
 
         var x = Decimal.Round(((a - b) + (c % d)) * e, 5) / f;
         var y = Math.Clamp(Decimal.Round(x++, 3), f, g);
-        var yfloor = Decimal.Floor(y);
-        var xceil = Decimal.Ceiling(x);
-        var z = --yfloor * ++xceil * -Decimal.Truncate(y);
+        var z = (Decimal.Floor(y) - 1) * (Decimal.Ceiling(x) + 1) * -Decimal.Truncate(y);
 
         Console.WriteLine($"x = {x}");
         Console.WriteLine($"y = {y}");
@@ -127,7 +132,7 @@ class Program
 }
 ```
 
-# 5. C++
+# 3.2. C++ Example
 
 This program illustrates the reference example using Windows App SDK's C++ decimal class.
 
@@ -151,18 +156,14 @@ int main()
     auto y = x++.round(3).clamp(f, g);
     auto z = --y.floor() * ++x.ceil() * -y.truncate();
 
-    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"x = %ls", x.to_string().c_str()));
-    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"y = %ls", y.to_string().c_str()));
-    WEX::Logging::Log::Comment(WEX::Common::String().Format(L"z = %ls", z.to_string().c_str()));
-
-    printf(L"x = %ls\n", x.to_string().c_str());
-    printf(L"y = %ls\n", y.to_string().c_str());
-    printf(L"z = %ls\n", z.to_string().c_str());
+    printf("x = %ls\n", x.to_wstring_invariant().c_str());
+    printf("y = %ls\n", y.to_wstring_invariant().c_str());
+    printf("z = %ls\n", z.to_wstring_invariant().c_str());
     return z.to_int32();
 }
 ```
 
-# 6. WinRT
+# 3.3. WinRT Example
 
 This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass.
 
@@ -176,9 +177,9 @@ int main()
     using DH = winrt::Microsoft::Windows::Foundation::DecimalHelper;
     const auto a{ DH::FromInt32(1) };
     const auto b{ DH::FromDouble(0.5) };
-    const auto c{ DH::FromString(L"-6.66") };
-    const auto d{ DH::FromString(L"1.23") };
-    const auto e{ DH::FromString(L"4567.089") };
+    const auto c{ DH::FromStringInvariant(L"-6.66") };
+    const auto d{ DH::FromStringInvariant(L"1.23") };
+    const auto e{ DH::FromStringInvariant(L"4567.089") };
     const auto f{ DH::FromInt64(-4ll) };
     const auto g{ DH::FromUInt16(1967u) };
     const auto h{ DH::FromSingle(1001.0f) };
@@ -195,16 +196,16 @@ int main()
     x = DH::Add(x, one);
     auto z = DH::Multiply(DH::Multiply(DH::Subtract(DH::Floor(y), one), DH::Add(DH::Ceiling(x), one)), DH::Negate(DH::Truncate(y)));
 
-    printf(L"x = %ls\n", DH::ToString(x).c_str());
-    printf(L"y = %ls\n", DH::ToString(y).c_str());
-    printf(L"z = %ls\n", DH::ToString(z).c_str());
+    printf(L"x = %ls\n", DH::ToStringInvariant(x).c_str());
+    printf(L"y = %ls\n", DH::ToStringInvariant(y).c_str());
+    printf(L"z = %ls\n", DH::ToStringInvariant(z).c_str());
     return DH::ToInt32(z);
 }
 ```
 
-# 7. WinRT API
+# 4. WinRT API
 
-Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure.
+Windows App SDK provides a `DecimalHelper` WinRT runtimeclass in addition to the `DecimalValue` structure.
 
 ```c# (but really MIDL3)
 namespace Microsoft.Windows.Foundation
@@ -241,10 +242,24 @@ namespace Microsoft.Windows.Foundation
         static DecimalValue FromUInt64(UInt64 value);
         static DecimalValue FromSingle(Single value);
         static DecimalValue FromDouble(Double value);
-        static DecimalValue FromString(String value);                          // LCID=LOCALE_INVARIANT
-        static DecimalValue FromStringWithSystemDefaultLocale(String value);   // LCID=GetSystemDefaultLCID()
-        static DecimalValue FromStringWithUserDefaultLocale(String value);     // LCID=GetUserDefaultLCID()
-        static DecimalValue FromStringWithThreadLocale(String value);          // LCID=GetThreadLocale()
+
+        /// Parse the string using the user's default locale.
+        static DecimalValue FromString(String value);
+
+        /// Parse the string using the invariant locale.
+        static DecimalValue FromStringInvariant(String value);
+
+        /// Parse the string using the specified locale.
+        static DecimalValue FromString(String value, String localeName);
+
+        /// Parse the string using the user's default locale.
+        static Boolean TryParseString(String value, DecimalValue* value);
+
+        /// Parse the string using the invariant locale.
+        static Boolean TryParseStringInvariant(String value, DecimalValue* value);
+
+        /// Parse the string using the specified locale.
+        static Boolean TryParseString(String value, String localeName, DecimalValue* value);
 
         static Boolean ToBoolean(DecimalValue value);
         static Int16 ToInt16(DecimalValue value);
@@ -256,10 +271,15 @@ namespace Microsoft.Windows.Foundation
         static UInt64 ToUInt64(DecimalValue value);
         static Single ToSingle(DecimalValue value);
         static Double ToDouble(DecimalValue value);
-        static String ToString(DecimalValue value);                         // LCID=LOCALE_INVARIANT
-        static String ToStringWithSystemDefaultLocale(DecimalValue value);  // LCID=GetSystemDefaultLCID()
-        static String ToStringWithUserDefaultLocale(DecimalValue value);    // LCID=GetUserDefaultLCID()
-        static String ToStringWithThreadLocale(DecimalValue value);         // LCID=GetThreadLocale()
+
+        /// Format the string using the user's default locale.
+        static String ToString(DecimalValue value);
+
+        /// Format the string using the invariant locale.
+        static String ToStringInvariant(DecimalValue value);
+
+        /// Format the string using the specified locale.
+        static String ToString(DecimalValue value, String localeName);
 
         /// Return true if (left == right).
         static Boolean Equals(DecimalValue left, DecimalValue right);
@@ -273,7 +293,7 @@ namespace Microsoft.Windows.Foundation
 
         /// Return the scaling factor of the value (the number of decimal digits).
         /// @return the scaling factor, ranging from 0 to max_scale().
-        static UInt32 Scale(DecimalValue value);
+        static UInt8 Scale(DecimalValue value);
 
         /// Return the sign of the value.
         /// @return 0 if value is zero, <0 if value is less than zero or >0 if value is greater than zero.
@@ -328,7 +348,7 @@ namespace Microsoft.Windows.Foundation
 }
 ```
 
-# 8. C++ API
+# 5. 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:
@@ -344,7 +364,7 @@ Windows App SDK provides a native language decimal data type for C++ as the
 
 Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception
 
-## 8.1. decimal.h
+## 5.1. decimal.h
 
 ```c++
 #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
@@ -381,7 +401,7 @@ public:
     decimal(const decimal& value);
     decimal(decimal&& value);
     constexpr decimal(const DECIMAL& value);
-    decimal(bool value)l
+    decimal(bool value);
     decimal(char value);
     decimal(std::int16_t value);
     decimal(std::int32_t value);
@@ -394,17 +414,102 @@ public:
     decimal(double value);
     decimal(long value);
     decimal(unsigned long value);
-    decimal(PCWSTR value);
-    decimal(PCWSTR value, const LCID locale);
-    decimal(const std::wstring& value);
-    decimal(const std::wstring& value, const LCID locale);
-#if defined(__WINSTRING_H_)
-    decimal(const HSTRING& value);
-    decimal(const HSTRING& value, const LCID locale);
-#endif // defined(__WINSTRING_H_)
+
+    /// Parse the string using the user's default locale.
+    static decimal from_string(PCWSTR source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_string_invariant(PCWSTR source);
+
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_string(PCWSTR source, PCWSTR localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_string(PCWSTR source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_string_invariant(PCWSTR source, decimal& value);
+
+    /// Parse the string using the specified locale.
+    static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value);
+
+    /// Parse the string using the user's default locale.
+    static decimal from_string(const std::string& source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_string_invariant(const std::string& source);
+
+    /// Parse the string using the specified locale.
+    static decimal from_string(const std::string& source, const std::string& localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_string(const std::string& source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_string_invariant(const std::string& source, decimal& value);
+
+    /// Parse bool try_string using the specified local, decimal& valuee.
+    static decimal from_string(const std::string& source, const std::string& localeName);
+
+    /// Parse the string using the user's default locale.
+    static decimal from_wstring(const std::wstring& source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_wstring_invariant(const std::wstring& source);
+
+    /// Parse the string using the specified locale.
+    static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_wstring(const std::wstring& source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_wstring_invariant(const std::wstring& source, decimal& value);
+
+    /// Parse bool try_string using the specified local, decimal& valuee.
+    static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme);
+
+#if defined(__hstring_h__)
+    /// Parse the string using the user's default locale.
+    static decimal from_hstring(const HSTRING& source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_hstring_invariant(const HSTRING& source);
+
+    /// Parse the string using the specified locale.
+    static decimal from_hstring(const HSTRING& source, const HSTRING& localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_hstring(const HSTRING& source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_hstring_invariant(const HSTRING& source, decimal& value);
+
+    /// Parse the string using the specified locale.
+    static bool try_from_hstring(const HSTRING& source, const HSTRING& localeName, decimal& value);
+#endif // defined(__hstring_h__)
+
 #if defined(WINRT_BASE_H)
-    decimal(const winrt::hstring& value);
-    decimal(const winrt::hstring& value, const LCID locale);
+    /// Parse the string using the user's default locale.
+    static decimal from_hstring(const winrt::hstring& source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_hstring_invariant(const winrt::hstring& source);
+
+    /// Parse the string using the specified locale.
+    static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeNAme);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_hstring(const winrt::hstring& source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value);
+
+    /// Parse the string using the specified locale.
+    static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value);
 #endif // defined(WINRT_BASE_H)
 
     decimal& operator=(const decimal& value);
@@ -423,14 +528,6 @@ public:
     decimal& operator=(double value);
     decimal& operator=(long value);
     decimal& operator=(unsigned long value);
-    decimal& operator=(PCWSTR value);
-    decimal& operator=(const std::wstring& value);
-#if defined(__WINSTRING_H_)
-    decimal& operator=(const HSTRING& value);
-#endif // defined(__WINSTRING_H_)
-#if defined(WINRT_BASE_H)
-    decimal& operator=(const winrt::hstring& value);
-#endif // defined(WINRT_BASE_H)
 
     const DECIMAL& to_decimal() const;
     bool to_bool() const;
@@ -446,15 +543,45 @@ public:
     double to_double() const;
     long to_long() const;
     unsigned long to_ulong() const;
-    std::wstring to_string() const;
-    std::wstring to_string(const LCID locale) const;
-#if defined(__WINSTRING_H_)
+
+    // Format the string using the user's default locale.
+    std::string to_string() const;
+
+    // Format the string using the invariant locale.
+    std::string to_string_invariant() const;
+
+    // Format the string using the specified locale.
+    std::string to_string(const std::string& localeName) const;
+
+    // Format the string using the user's default locale.
+    std::wstring to_wstring() const;
+
+    // Format the string using the invariant locale.
+    std::wstring to_wstring_invariant() const;
+
+    // Format the string using the invariant locale.
+    std::wstring to_wstring(const std::wstring& localeName) const;
+
+#if defined(__hstring_h__)
+    // Format the string using the user's default locale.
     HSTRING to_HSTRING() const;
-    HSTRING to_HSTRING(const LCID locale) const;
-#endif // defined(WINRT_BASE_H)
+
+    // Format the string using the specified locale.
+    HSTRING to_HSTRING_invariant() const;
+
+    // Format the string using the specified locale.
+    HSTRING to_HSTRING(const HSTRING& localeName) const;
+#endif // defined(__hstring_h__)
+
 #if defined(WINRT_BASE_H)
+    // Format the string using the user's default locale.
     winrt::hstring to_hstring() const;
-    winrt::hstring to_hstring(const LCID locale) const;
+
+    // Format the string using the specified locale.
+    winrt::hstring to_hstring_invariant() const;
+
+    // Format the string using the specified locale.
+    winrt::hstring to_hstring(const winrt::hstring& localeName) const;
 #endif // defined(WINRT_BASE_H)
 
     bool operator==(const decimal& value) const;
@@ -481,7 +608,7 @@ public:
 
     /// 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;
+    std::uint8_t scale() const;
 
     /// 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.
@@ -548,7 +675,7 @@ private:
 #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
 ```
 
-## 8.2. decimalcppwinmrt.h
+## 5.2. decimalcppwinrt.h
 
 This header provides C++/WinRT and Windows App SDK's DecimalValue integration.
 
@@ -625,7 +752,7 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic
 #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)
 ```
 
-# 9. C# API
+# 6. C# API
 
 C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal).
 Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`.
@@ -639,7 +766,7 @@ namespace Microsoft.Windows.Foundation
         public static Microsoft.Windows.Foundation.DecimalValue ToDecimalValue(this decimal d);
 
         /// Return a C# Decimal object.
-        public static decimal FromDecimalValue(this decimal d, Microsoft.Windows.Foundation.DecimalValue value);
+        public static decimal ToDecimal(this decimal d, Microsoft.Windows.Foundation.DecimalValue value);
     }
 }
 ```

From 40e6407e7f03b2aef4cf1fba912b73022025874e Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 26 May 2025 12:07:27 -0700
Subject: [PATCH 05/10] Incorporated feedback

---
 specs/decimal/decimal.md | 84 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 3 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 994524e530..7599ccc1aa 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -402,7 +402,6 @@ public:
     decimal(decimal&& value);
     constexpr decimal(const DECIMAL& value);
     decimal(bool value);
-    decimal(char value);
     decimal(std::int16_t value);
     decimal(std::int32_t value);
     decimal(std::int64_t value);
@@ -415,6 +414,31 @@ public:
     decimal(long value);
     decimal(unsigned long value);
 
+    //---- Parse String: PCSTR
+
+    /// Parse the string using the user's default locale.
+    static decimal from_string(PCSTR source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_string_invariant(PCSTR source);
+
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale.
+    static decimal from_string(PCSTR source, PCSTR localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_string(PCSTR source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_string_invariant(PCSTR source, decimal& value);
+
+    /// Parse the string using the specified locale.
+    static bool try_from_string(PCSTR source, PCSTR localeName, decimal& value);
+
+    //---- Parse String: PCWSTR
+
     /// Parse the string using the user's default locale.
     static decimal from_string(PCWSTR source);
 
@@ -436,6 +460,8 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value);
 
+    //---- Parse String: std::string
+
     /// Parse the string using the user's default locale.
     static decimal from_string(const std::string& source);
 
@@ -454,6 +480,28 @@ public:
     /// Parse bool try_string using the specified local, decimal& valuee.
     static decimal from_string(const std::string& source, const std::string& localeName);
 
+    //---- Parse String: std::string_value
+
+    /// Parse the string_value using the user's default locale.
+    static decimal from_string_value(const std::string_value& source);
+
+    /// Parse the string_value using the invariant locale.
+    static decimal from_string_value_invariant(const std::string_value& source);
+
+    /// Parse the string_value using the specified locale.
+    static decimal from_string_value(const std::string_value& source, const std::string_value& localeName);
+
+    /// Parse the string_value using the user's default locale.
+    static bool try_from_string_value(const std::string_value& source, decimal& value);
+
+    /// Parse the string_value using the invariant locale.
+    static bool try_from_string_value_invariant(const std::string_value& source, decimal& value);
+
+    /// Parse bool try_string_value using the specified local, decimal& valuee.
+    static decimal from_string_value(const std::string_value& source, const std::string_value& localeName);
+
+    //---- Parse String: std::wstring
+
     /// Parse the string using the user's default locale.
     static decimal from_wstring(const std::wstring& source);
 
@@ -472,7 +520,29 @@ public:
     /// Parse bool try_string using the specified local, decimal& valuee.
     static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme);
 
+    //---- Parse String: std::wstring_value
+
+    /// Parse the string using the user's default locale.
+    static decimal from_wstring_value(const std::wstring_value& source);
+
+    /// Parse the string using the invariant locale.
+    static decimal from_wstring_value_invariant(const std::wstring_value& source);
+
+    /// Parse the string using the specified locale.
+    static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeName);
+
+    /// Parse the string using the user's default locale.
+    static bool try_from_wstring_value(const std::wstring_value& source, decimal& value);
+
+    /// Parse the string using the invariant locale.
+    static bool try_from_wstring_value_invariant(const std::wstring_value& source, decimal& value);
+
+    /// Parse bool try_string using the specified local, decimal& valuee.
+    static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeNAme);
+
 #if defined(__hstring_h__)
+    //---- Parse String: HSTRING
+
     /// Parse the string using the user's default locale.
     static decimal from_hstring(const HSTRING& source);
 
@@ -493,6 +563,8 @@ public:
 #endif // defined(__hstring_h__)
 
 #if defined(WINRT_BASE_H)
+    //---- Parse String: winrt::hstring
+
     /// Parse the string using the user's default locale.
     static decimal from_hstring(const winrt::hstring& source);
 
@@ -516,7 +588,6 @@ public:
     decimal& operator=(decimal&& value);
     decimal& operator=(const DECIMAL& value);
     decimal& operator=(bool value);
-    decimal& operator=(char value);
     decimal& operator=(std::int16_t value);
     decimal& operator=(std::int32_t value);
     decimal& operator=(std::int64_t value);
@@ -531,7 +602,6 @@ public:
 
     const DECIMAL& to_decimal() const;
     bool to_bool() const;
-    char to_char() const;
     std::int16_t to_int16() const;
     std::int32_t to_int32() const;
     std::int64_t to_int64() const;
@@ -544,6 +614,8 @@ public:
     long to_long() const;
     unsigned long to_ulong() const;
 
+    //---- Parse String: std::string
+
     // Format the string using the user's default locale.
     std::string to_string() const;
 
@@ -553,6 +625,8 @@ public:
     // Format the string using the specified locale.
     std::string to_string(const std::string& localeName) const;
 
+    //---- Parse String: std::wstring
+
     // Format the string using the user's default locale.
     std::wstring to_wstring() const;
 
@@ -563,6 +637,8 @@ public:
     std::wstring to_wstring(const std::wstring& localeName) const;
 
 #if defined(__hstring_h__)
+    //---- Parse String: HSTRING
+
     // Format the string using the user's default locale.
     HSTRING to_HSTRING() const;
 
@@ -574,6 +650,8 @@ public:
 #endif // defined(__hstring_h__)
 
 #if defined(WINRT_BASE_H)
+    //---- Parse String: winrt::hstring
+
     // Format the string using the user's default locale.
     winrt::hstring to_hstring() const;
 

From 8f0ce08a14864a025dd2d8d20b0bc11aa4644d48 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 9 Jun 2025 10:38:20 -0700
Subject: [PATCH 06/10] Incorporated feedback

---
 specs/decimal/decimal.md | 337 ++++++++++++++++++++++++++++-----------
 1 file changed, 241 insertions(+), 96 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 7599ccc1aa..8278217f40 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -145,9 +145,9 @@ int main()
 {
     const Microsoft::Windows::Foundation::decimal a{ 1 };
     const Microsoft::Windows::Foundation::decimal b{ 0.5 };
-    const Microsoft::Windows::Foundation::decimal c{ L"-6.66" };
-    const Microsoft::Windows::Foundation::decimal d{ L"1.23" };
-    const Microsoft::Windows::Foundation::decimal e{ L"4567.089" };
+    const auto c{ Microsoft::Windows::Foundation::decimal::from_string("-6.66") };
+    const auto d{ Microsoft::Windows::Foundation::decimal::from_string("1.23") };
+    const auto e{ Microsoft::Windows::Foundation::decimal::from_string("4567.089" };
     const Microsoft::Windows::Foundation::decimal f{ -4ll };
     const Microsoft::Windows::Foundation::decimal g{ 1967u };
     const Microsoft::Windows::Foundation::decimal h{ 1001.0f };
@@ -244,22 +244,24 @@ namespace Microsoft.Windows.Foundation
         static DecimalValue FromDouble(Double value);
 
         /// Parse the string using the user's default locale.
-        static DecimalValue FromString(String value);
+        static DecimalValue FromString(String source);
 
         /// Parse the string using the invariant locale.
-        static DecimalValue FromStringInvariant(String value);
+        static DecimalValue FromStringInvariant(String source);
 
         /// Parse the string using the specified locale.
-        static DecimalValue FromString(String value, String localeName);
+        [method_name("FromStringWithLocale")]
+        static DecimalValue FromString(String source, String localeName);
 
         /// Parse the string using the user's default locale.
-        static Boolean TryParseString(String value, DecimalValue* value);
+        static Boolean TryFromString(String source, out DecimalValue value);
 
         /// Parse the string using the invariant locale.
-        static Boolean TryParseStringInvariant(String value, DecimalValue* value);
+        static Boolean TryFromStringInvariant(String source, out DecimalValue value);
 
         /// Parse the string using the specified locale.
-        static Boolean TryParseString(String value, String localeName, DecimalValue* value);
+        [method_name("TryFromStringWithLocale")]
+        static Boolean TryFromString(String source, String localeName, out DecimalValue value);
 
         static Boolean ToBoolean(DecimalValue value);
         static Int16 ToInt16(DecimalValue value);
@@ -279,6 +281,7 @@ namespace Microsoft.Windows.Foundation
         static String ToStringInvariant(DecimalValue value);
 
         /// Format the string using the specified locale.
+        [method_name("ToStringWithLocale")]
         static String ToString(DecimalValue value, String localeName);
 
         /// Return true if (left == right).
@@ -291,6 +294,9 @@ namespace Microsoft.Windows.Foundation
         /// Return true if the value is valid.
         static Boolean IsValid(DecimalValue value);
 
+        /// Return true if value is an integral number.
+        static Boolean IsInteger(DecimalValue value);
+
         /// Return the scaling factor of the value (the number of decimal digits).
         /// @return the scaling factor, ranging from 0 to max_scale().
         static UInt8 Scale(DecimalValue value);
@@ -300,7 +306,7 @@ namespace Microsoft.Windows.Foundation
         static Int32 Sign(DecimalValue value);
 
         /// Return the maximum scaling factor
-        static UInt32 MaxScale();
+        static UInt8 MaxScale();
 
         /// Return the maximum value (79,228,162,514,264,337,593,543,950,335).
         static DecimalValue MaxValue();
@@ -354,13 +360,15 @@ 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
+* to_xxx() methods converting a decimal object's value to various string data types
+* [try]_from_xxx() methods converting a decimal object's value from various string data types
 * Relational operations: `compare()` `==` `!=` `<` `<=` `>` `>=`
-* Unary operations: + - ++ --
-* Binary operations: + += - -= * *= / /= % %=
+* Unary operations: `+` `-` `++` `--`
+* Binary operations: `+` `+=` `-` `-=` `*` `*=` `/` `/=` `%` `%=`
 * Properties: `sign()` `scale()`
 * Mathematical operations: `abs()` `truncate()` `floor()` `ceil()` `round()` `clamp()`
 * Constants: `max_scale()` `max_value()` `min_value()`
+* Validation: `is_integer()` `is_valid()`
 
 Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception
 
@@ -399,23 +407,36 @@ public:
     ~decimal() = default;
 
     decimal(const decimal& value);
+
     decimal(decimal&& value);
+
     constexpr decimal(const DECIMAL& value);
+
     decimal(bool value);
+
     decimal(std::int16_t value);
+
     decimal(std::int32_t value);
+
     decimal(std::int64_t value);
+
     decimal(std::uint8_t value);
+
     decimal(std::uint16_t value);
+
     decimal(std::uint32_t value);
+
     decimal(std::uint64_t value);
+
     decimal(float value);
+
     decimal(double value);
+
     decimal(long value);
-    decimal(unsigned long value);
 
-    //---- Parse String: PCSTR
+    decimal(unsigned long value);
 
+public:
     /// Parse the string using the user's default locale.
     static decimal from_string(PCSTR source);
 
@@ -424,7 +445,7 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
     /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale.
     static decimal from_string(PCSTR source, PCSTR localeName);
 
@@ -437,8 +458,7 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_string(PCSTR source, PCSTR localeName, decimal& value);
 
-    //---- Parse String: PCWSTR
-
+public:
     /// Parse the string using the user's default locale.
     static decimal from_string(PCWSTR source);
 
@@ -447,7 +467,7 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
     /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_string(PCWSTR source, PCWSTR localeName);
 
@@ -460,8 +480,7 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value);
 
-    //---- Parse String: std::string
-
+public:
     /// Parse the string using the user's default locale.
     static decimal from_string(const std::string& source);
 
@@ -469,6 +488,9 @@ public:
     static decimal from_string_invariant(const std::string& source);
 
     /// Parse the string using the specified locale.
+    /// @note localeName="!x-sys-default-locale" for the system default locale.
+    /// @note localeName=NULL for the invariant locale.
+    /// @note localeName="" for the user default locale.
     static decimal from_string(const std::string& source, const std::string& localeName);
 
     /// Parse the string using the user's default locale.
@@ -477,31 +499,32 @@ public:
     /// Parse the string using the invariant locale.
     static bool try_from_string_invariant(const std::string& source, decimal& value);
 
-    /// Parse bool try_string using the specified local, decimal& valuee.
-    static decimal from_string(const std::string& source, const std::string& localeName);
-
-    //---- Parse String: std::string_value
-
-    /// Parse the string_value using the user's default locale.
-    static decimal from_string_value(const std::string_value& source);
+    /// Parse the string using the specified locale.
+    static bool try_from_string(const std::string& source, const std::string& localeName, decimal& value);
 
-    /// Parse the string_value using the invariant locale.
-    static decimal from_string_value_invariant(const std::string_value& source);
+public:
+    /// Parse the string using the user's default locale.
+    static decimal from_string_view(const std::string_view& source);
 
-    /// Parse the string_value using the specified locale.
-    static decimal from_string_value(const std::string_value& source, const std::string_value& localeName);
+    /// Parse the string using the invariant locale.
+    static decimal from_string_view_invariant(const std::string_view& source);
 
-    /// Parse the string_value using the user's default locale.
-    static bool try_from_string_value(const std::string_value& source, decimal& value);
+    /// Parse the string using the specified locale.
+    /// @note localeName="!x-sys-default-locale" for the system default locale.
+    /// @note localeName=NULL for the invariant locale.
+    /// @note localeName="" for the user default locale.
+    static decimal from_string_view(const std::string_view& source, const std::string_view& localeName);
 
-    /// Parse the string_value using the invariant locale.
-    static bool try_from_string_value_invariant(const std::string_value& source, decimal& value);
+    /// Parse the string using the user's default locale.
+    static bool try_from_string_view(const std::string_view& source, decimal& value);
 
-    /// Parse bool try_string_value using the specified local, decimal& valuee.
-    static decimal from_string_value(const std::string_value& source, const std::string_value& localeName);
+    /// Parse the string using the invariant locale.
+    static bool try_from_string_view_invariant(const std::string_view& source, decimal& value);
 
-    //---- Parse String: std::wstring
+    /// Parse the string using the specified locale.
+    static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value);
 
+public:
     /// Parse the string using the user's default locale.
     static decimal from_wstring(const std::wstring& source);
 
@@ -509,6 +532,9 @@ public:
     static decimal from_wstring_invariant(const std::wstring& source);
 
     /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
 
     /// Parse the string using the user's default locale.
@@ -517,105 +543,156 @@ public:
     /// Parse the string using the invariant locale.
     static bool try_from_wstring_invariant(const std::wstring& source, decimal& value);
 
-    /// Parse bool try_string using the specified local, decimal& valuee.
-    static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme);
-
-    //---- Parse String: std::wstring_value
+    /// Parse the string using the specified locale.
+    static bool try_from_wstring(const std::wstring& source, const std::wstring& localeName, decimal& value);
 
+public:
     /// Parse the string using the user's default locale.
-    static decimal from_wstring_value(const std::wstring_value& source);
+    static decimal from_wstring_view(const std::wstring_view& source);
 
     /// Parse the string using the invariant locale.
-    static decimal from_wstring_value_invariant(const std::wstring_value& source);
+    static decimal from_wstring_view_invariant(const std::wstring_view& source);
 
     /// Parse the string using the specified locale.
-    static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeName);
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName);
 
     /// Parse the string using the user's default locale.
-    static bool try_from_wstring_value(const std::wstring_value& source, decimal& value);
+    static bool try_from_wstring_view(const std::wstring_view& source, decimal& value);
 
     /// Parse the string using the invariant locale.
-    static bool try_from_wstring_value_invariant(const std::wstring_value& source, decimal& value);
+    static bool try_from_wstring_view_invariant(const std::wstring_view& source, decimal& value);
 
-    /// Parse bool try_string using the specified local, decimal& valuee.
-    static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeNAme);
+    /// Parse the string using the specified locale.
+    static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value);
 
+public:
 #if defined(__hstring_h__)
-    //---- Parse String: HSTRING
-
     /// Parse the string using the user's default locale.
-    static decimal from_hstring(const HSTRING& source);
+    static decimal from_HSTRING(const HSTRING& source);
+#endif // defined(__hstring_h__)
 
+#if defined(__hstring_h__)
     /// Parse the string using the invariant locale.
-    static decimal from_hstring_invariant(const HSTRING& source);
+    static decimal from_HSTRING_invariant(const HSTRING& source);
+#endif // defined(__hstring_h__)
 
+#if defined(__hstring_h__)
     /// Parse the string using the specified locale.
-    static decimal from_hstring(const HSTRING& source, const HSTRING& localeName);
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName);
+#endif // defined(__hstring_h__)
 
+#if defined(__hstring_h__)
     /// Parse the string using the user's default locale.
-    static bool try_from_hstring(const HSTRING& source, decimal& value);
+    static bool try_from_HSTRING(const HSTRING& source, decimal& value);
+#endif // defined(__hstring_h__)
 
+#if defined(__hstring_h__)
     /// Parse the string using the invariant locale.
-    static bool try_from_hstring_invariant(const HSTRING& source, decimal& value);
+    static bool try_from_HSTRING_invariant(const HSTRING& source, decimal& value);
+#endif // defined(__hstring_h__)
 
+#if defined(__hstring_h__)
     /// Parse the string using the specified locale.
-    static bool try_from_hstring(const HSTRING& source, const HSTRING& localeName, decimal& value);
+    static bool try_from_HSTRING(const HSTRING& source, const HSTRING& localeName, decimal& value);
 #endif // defined(__hstring_h__)
 
+public:
 #if defined(WINRT_BASE_H)
-    //---- Parse String: winrt::hstring
-
     /// Parse the string using the user's default locale.
     static decimal from_hstring(const winrt::hstring& source);
+#endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
     /// Parse the string using the invariant locale.
     static decimal from_hstring_invariant(const winrt::hstring& source);
+#endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
     /// Parse the string using the specified locale.
-    static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeNAme);
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName);
+#endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
     /// Parse the string using the user's default locale.
     static bool try_from_hstring(const winrt::hstring& source, decimal& value);
+#endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
     /// Parse the string using the invariant locale.
     static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value);
+#endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
     /// Parse the string using the specified locale.
     static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value);
 #endif // defined(WINRT_BASE_H)
 
     decimal& operator=(const decimal& value);
+
     decimal& operator=(decimal&& value);
+
     decimal& operator=(const DECIMAL& value);
+
     decimal& operator=(bool value);
+
     decimal& operator=(std::int16_t value);
+
     decimal& operator=(std::int32_t value);
+
     decimal& operator=(std::int64_t value);
+
     decimal& operator=(std::uint8_t value);
+
     decimal& operator=(std::uint16_t value);
+
     decimal& operator=(std::uint32_t value);
+
     decimal& operator=(std::uint64_t value);
+
     decimal& operator=(float value);
+
     decimal& operator=(double value);
+
     decimal& operator=(long value);
+
     decimal& operator=(unsigned long value);
 
     const DECIMAL& to_decimal() const;
+
     bool to_bool() const;
+
     std::int16_t to_int16() const;
+
     std::int32_t to_int32() const;
+
     std::int64_t to_int64() const;
+
     std::uint8_t to_uint8() const;
+
     std::uint16_t to_uint16() const;
+
     std::uint32_t to_uint32() const;
+
     std::uint64_t to_uint64() const;
+
     float to_float() const;
+
     double to_double() const;
+
     long to_long() const;
-    unsigned long to_ulong() const;
 
-    //---- Parse String: std::string
+    unsigned long to_ulong() const;
 
+public:
     // Format the string using the user's default locale.
     std::string to_string() const;
 
@@ -623,67 +700,96 @@ public:
     std::string to_string_invariant() const;
 
     // Format the string using the specified locale.
-    std::string to_string(const std::string& localeName) const;
+    std::string to_string(PCWSTR localeName) const;
 
-    //---- Parse String: std::wstring
+    // Format the string using the specified locale.
+    std::string to_string(const std::string& localeName) const;
 
+public:
     // Format the string using the user's default locale.
     std::wstring to_wstring() const;
 
     // Format the string using the invariant locale.
     std::wstring to_wstring_invariant() const;
 
-    // Format the string using the invariant locale.
+    // Format the string using the specified locale.
     std::wstring to_wstring(const std::wstring& localeName) const;
 
-#if defined(__hstring_h__)
-    //---- Parse String: HSTRING
+    // Format the string using the specified locale.
+    std::wstring to_wstring(PCWSTR localeName) const;
 
-    // Format the string using the user's default locale.
+public:
+#if defined(__hstring_h__)
     HSTRING to_HSTRING() const;
+#endif // defined(__hstring_h__)
 
-    // Format the string using the specified locale.
+#if defined(__hstring_h__)
     HSTRING to_HSTRING_invariant() const;
+#endif // defined(__hstring_h__)
 
-    // Format the string using the specified locale.
+#if defined(__hstring_h__)
     HSTRING to_HSTRING(const HSTRING& localeName) const;
 #endif // defined(__hstring_h__)
 
-#if defined(WINRT_BASE_H)
-    //---- Parse String: winrt::hstring
+#if defined(__hstring_h__)
+    HSTRING to_HSTRING(PCWSTR localeName) const;
+#endif // defined(__hstring_h__)
 
-    // Format the string using the user's default locale.
+public:
+#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring() const;
+#endif // defined(WINRT_BASE_H)
 
-    // Format the string using the specified locale.
+#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring_invariant() const;
+#endif // defined(WINRT_BASE_H)
 
-    // Format the string using the specified locale.
+#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring(const winrt::hstring& localeName) const;
 #endif // defined(WINRT_BASE_H)
 
+#if defined(WINRT_BASE_H)
+    winrt::hstring to_hstring(PCWSTR localeName) const;
+#endif // defined(WINRT_BASE_H)
+
+public:
     bool operator==(const decimal& value) const;
+
     bool operator!=(const decimal& value) const;
+
     bool operator< (const decimal& value) const;
+
     bool operator<=(const decimal& value) const;
+
     bool operator> (const decimal& value) const;
+
     bool operator>=(const decimal& value) const;
+
     int compare(const decimal& value) const;
 
     bool operator==(const DECIMAL& value) const;
+
     bool operator!=(const DECIMAL& value) const;
+
     bool operator< (const DECIMAL& value) const;
+
     bool operator<=(const DECIMAL& value) const;
+
     bool operator> (const DECIMAL& value) const;
+
     bool operator>=(const DECIMAL& value) const;
-    int compare(const DECIMAL& value) const;
 
-    /// Return true if this is valid.
-    bool is_valid();
+    int compare(const DECIMAL& value) const;
 
     /// Return true if value is valid.
     static constexpr bool is_valid(const DECIMAL& value);
 
+    /// Return true if this is an integral number.
+    bool is_integer() const;
+
+    /// Return true if value is an integral number.
+    static constexpr bool is_integer(const 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::uint8_t scale() const;
@@ -693,7 +799,7 @@ public:
     std::int32_t sign() const;
 
     /// Return the maximum scaling factor
-    static constexpr std::uint32_t max_scale();
+    static constexpr std::uint8_t max_scale();
 
     /// Return the maximum value (79,228,162,514,264,337,593,543,950,335).
     static constexpr decimal max_value();
@@ -721,32 +827,38 @@ public:
     decimal clamp(decimal min, decimal max) const;
 
     decimal operator++();
+
     decimal operator++(int);
 
     decimal operator--();
+
     decimal operator--(int);
 
     decimal operator+(const decimal& value) const;
+
+    decimal& operator+=(const decimal& value);
+
     decimal operator-(const decimal& value) const;
+
+    decimal& operator-=(const decimal& value);
+
     decimal operator*(const decimal& value) const;
+
+    decimal& operator*=(const decimal& value);
+
     decimal operator/(const decimal& value) const;
 
+    decimal& operator/=(const decimal& value);
+
     /// 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;
 
-    decimal& operator+=(const decimal& value);
-    decimal& operator-=(const decimal& value);
-    decimal& operator*=(const decimal& value);
-    decimal& operator/=(const decimal& value);
     decimal& operator%=(const decimal& value);
 
     decimal round(const std::int32_t decimalPlaces) const;
-
-private:
-    DECIMAL m_decimal{};
 };
 }
 
@@ -775,10 +887,16 @@ This header provides C++/WinRT and Windows App SDK's DecimalValue integration.
 namespace winrt::Microsoft::Windows::Foundation
 {
 /// Return value as a Win32 DECIMAL structure.
-inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value)
+{
+    return std::bit_cast<DECIMAL>(value);
+}
 
 /// Return value as a WinRT DecimalValue structure.
-inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value);
+inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value)
+{
+    return std::bit_cast<winrt::Microsoft::Windows::Foundation::DecimalValue>(value);
+}
 }
 
 //----------------------------------------------------------
@@ -790,19 +908,31 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIM
 
 inline bool operator<(
     winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
-    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right)
+{
+    return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) < 0;
+}
 
 inline bool operator<=(
     winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
-    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right)
+{
+    return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) <= 0;
+}
 
 inline bool operator>(
     winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
-    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right)
+{
+    return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) > 0;
+}
 
 inline bool operator>=(
     winrt::Microsoft::Windows::Foundation::DecimalValue const& left,
-    winrt::Microsoft::Windows::Foundation::DecimalValue const& right);
+    winrt::Microsoft::Windows::Foundation::DecimalValue const& right)
+{
+    return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) >= 0;
+}
 
 #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_)
 
@@ -818,13 +948,28 @@ inline bool operator>=(
 namespace winrt::Microsoft::Windows::Foundation
 {
 /// Return true if value is valid.
-constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value)
+{
+    return ::Microsoft::Windows::Foundation::decimal::is_valid(to_DECIMAL(value));
+}
+
+/// Return true if value is an integral number.
+constexpr bool is_integer(winrt::Microsoft::Windows::Foundation::DecimalValue const& value)
+{
+    return ::Microsoft::Windows::Foundation::decimal::is_integer(to_DECIMAL(value));
+}
 
 /// Return value as a C++ decimal object.
-inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value);
+inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value)
+{
+    return ::Microsoft::Windows::Foundation::decimal{ to_DECIMAL(value) };
+}
 
 /// Return value as a WinRT DecimalValue structure.
-inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value);
+inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value)
+{
+    return to_DecimalValue(value.to_decimal());
+}
 }
 
 #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)

From a3c74f98ad895c89f3640f4e864590adf8b6f2d3 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 9 Jun 2025 10:46:43 -0700
Subject: [PATCH 07/10] Incorporated feedback

---
 specs/decimal/decimal.md | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 8278217f40..98f6524626 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -1,19 +1,17 @@
 - [1. Decimal](#1-decimal)
 - [2. Common Decimal Representation](#2-common-decimal-representation)
 - [3. Examples](#3-examples)
-- [4. C#](#4-c)
-- [5. C++](#5-c)
-- [6. WinRT](#6-winrt)
+- [4. C# Example](#4-c-example)
+- [5. C++ Example](#5-c-example)
+- [6. WinRT Example](#6-winrt-example)
 - [7. WinRT API](#7-winrt-api)
 - [8. C++ API](#8-c-api)
   - [8.1. decimal.h](#81-decimalh)
-  - [8.2. decimalcppwinmrt.h](#82-decimalcppwinrth)
+  - [8.2. decimalcppwinrt.h](#82-decimalcppwinrth)
 - [9. C# API](#9-c-api)
 
 # 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)
@@ -97,7 +95,7 @@ z == -1540
 
 and the process exit code is -1540.
 
-# 3.1. C# Example
+# 4. C# Example
 
 NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal)
 providing the canonical reference for examples in other languages.
@@ -132,7 +130,7 @@ class Program
 }
 ```
 
-# 3.2. C++ Example
+# 5. C++ Example
 
 This program illustrates the reference example using Windows App SDK's C++ decimal class.
 
@@ -163,7 +161,7 @@ int main()
 }
 ```
 
-# 3.3. WinRT Example
+# 6. WinRT Example
 
 This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass.
 
@@ -203,7 +201,7 @@ int main()
 }
 ```
 
-# 4. WinRT API
+# 7. WinRT API
 
 Windows App SDK provides a `DecimalHelper` WinRT runtimeclass in addition to the `DecimalValue` structure.
 
@@ -354,7 +352,7 @@ namespace Microsoft.Windows.Foundation
 }
 ```
 
-# 5. C++ API
+# 8. 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:
@@ -372,7 +370,7 @@ Windows App SDK provides a native language decimal data type for C++ as the
 
 Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception
 
-## 5.1. decimal.h
+## 8.1. decimal.h
 
 ```c++
 #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
@@ -865,7 +863,7 @@ public:
 #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
 ```
 
-## 5.2. decimalcppwinrt.h
+## 8.2. decimalcppwinrt.h
 
 This header provides C++/WinRT and Windows App SDK's DecimalValue integration.
 
@@ -975,7 +973,7 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic
 #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_)
 ```
 
-# 6. C# API
+# 9. C# API
 
 C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal).
 Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`.

From 2289225a2bf560c53048eea457308f4bbd18d7db Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 9 Jun 2025 22:22:41 -0700
Subject: [PATCH 08/10] Corrected syntax errors

---
 specs/decimal/decimal.md | 106 +++++++++++++++++++++++++--------------
 1 file changed, 69 insertions(+), 37 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index 98f6524626..c0c9100501 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -100,7 +100,7 @@ and the process exit code is -1540.
 NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal)
 providing the canonical reference for examples in other languages.
 
-```c++
+```c#
 Using System;
 Using System.IO;
 
@@ -373,11 +373,21 @@ Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will t
 ## 8.1. decimal.h
 
 ```c++
+// Copyright (c) Microsoft Corporation and Contributors.
+// Licensed under the MIT License.
+
 #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_)
 #define __WindowsAppSDK_Microsoft_Windows_Foundation_decimal_
 
+#include <winnls.h>
 #include <oleauto.h>
 
+#include <string>
+
+#include <wil/cppwinrt.h>
+#include <wil/resource.h>
+#include <wil/result_macros.h>
+
 #if !defined(_VC_NODEFAULTLIB)
 #pragma comment(linker, "/defaultlib:oleaut32.lib")
 #endif
@@ -491,6 +501,12 @@ public:
     /// @note localeName="" for the user default locale.
     static decimal from_string(const std::string& source, const std::string& localeName);
 
+    /// Parse the string using the specified locale.
+    /// @note localeName="!x-sys-default-locale" for the system default locale.
+    /// @note localeName=NULL for the invariant locale.
+    /// @note localeName="" for the user default locale.
+    static decimal from_string(const std::string& source, const PCSTR localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_string(const std::string& source, decimal& value);
 
@@ -500,6 +516,9 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_string(const std::string& source, const std::string& localeName, decimal& value);
 
+    /// Parse the string using the specified locale.
+    static bool try_from_string(const std::string& source, PCSTR localeName, decimal& value);
+
 public:
     /// Parse the string using the user's default locale.
     static decimal from_string_view(const std::string_view& source);
@@ -513,12 +532,21 @@ public:
     /// @note localeName="" for the user default locale.
     static decimal from_string_view(const std::string_view& source, const std::string_view& localeName);
 
+    /// Parse the string using the specified locale.
+    /// @note localeName="!x-sys-default-locale" for the system default locale.
+    /// @note localeName=NULL for the invariant locale.
+    /// @note localeName="" for the user default locale.
+    static decimal from_string_view(const std::string_view& source, PCSTR localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_string_view(const std::string_view& source, decimal& value);
 
     /// Parse the string using the invariant locale.
     static bool try_from_string_view_invariant(const std::string_view& source, decimal& value);
 
+    /// Parse the string using the specified locale.
+    static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value)
+
     /// Parse the string using the specified locale.
     static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value);
 
@@ -535,6 +563,12 @@ public:
     /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
 
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_wstring(const std::wstring& source, decimal& value);
 
@@ -544,6 +578,9 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_wstring(const std::wstring& source, const std::wstring& localeName, decimal& value);
 
+    /// Parse the string using the specified locale.
+    static bool try_from_wstring(const std::wstring& source, PCWSTR localeName, decimal& value);
+
 public:
     /// Parse the string using the user's default locale.
     static decimal from_wstring_view(const std::wstring_view& source);
@@ -557,6 +594,12 @@ public:
     /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName);
 
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_wstring_view(const std::wstring_view& source, decimal& value);
 
@@ -566,70 +609,71 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value);
 
+    /// Parse the string using the specified locale.
+    static bool try_from_wstring_view(const std::wstring_view& source, PCWSTR localeName, decimal& value);
+
 public:
-#if defined(__hstring_h__)
+#if defined(__hstring_h__) && defined(__WINSTRING_H_)
     /// Parse the string using the user's default locale.
     static decimal from_HSTRING(const HSTRING& source);
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     /// Parse the string using the invariant locale.
     static decimal from_HSTRING_invariant(const HSTRING& source);
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
     /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
     /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName);
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_HSTRING(const HSTRING& source, decimal& value);
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     /// Parse the string using the invariant locale.
     static bool try_from_HSTRING_invariant(const HSTRING& source, decimal& value);
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     /// Parse the string using the specified locale.
     static bool try_from_HSTRING(const HSTRING& source, const HSTRING& localeName, decimal& value);
-#endif // defined(__hstring_h__)
+
+    /// Parse the string using the specified locale.
+    static bool try_from_HSTRING(const HSTRING& source, PCWSTR localeName, decimal& value);
+#endif // defined(__hstring_h__) && defined(__WINSTRING_H_)
 
 public:
 #if defined(WINRT_BASE_H)
     /// Parse the string using the user's default locale.
     static decimal from_hstring(const winrt::hstring& source);
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     /// Parse the string using the invariant locale.
     static decimal from_hstring_invariant(const winrt::hstring& source);
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
     /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
     /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
     static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName);
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
+    /// Parse the string using the specified locale.
+    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
+    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    static decimal from_hstring(const winrt::hstring& source, PCWSTR localeName);
+
     /// Parse the string using the user's default locale.
     static bool try_from_hstring(const winrt::hstring& source, decimal& value);
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     /// Parse the string using the invariant locale.
     static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value);
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
+    /// Parse the string using the specified locale.
+    static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value)
+
     /// Parse the string using the specified locale.
     static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value);
 #endif // defined(WINRT_BASE_H)
@@ -717,36 +761,24 @@ public:
     std::wstring to_wstring(PCWSTR localeName) const;
 
 public:
-#if defined(__hstring_h__)
+#if defined(__hstring_h__) && defined(__WINSTRING_H_)
     HSTRING to_HSTRING() const;
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     HSTRING to_HSTRING_invariant() const;
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     HSTRING to_HSTRING(const HSTRING& localeName) const;
-#endif // defined(__hstring_h__)
 
-#if defined(__hstring_h__)
     HSTRING to_HSTRING(PCWSTR localeName) const;
-#endif // defined(__hstring_h__)
+#endif // defined(__hstring_h__) && defined(__WINSTRING_H_)
 
 public:
 #if defined(WINRT_BASE_H)
     winrt::hstring to_hstring() const;
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring_invariant() const;
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring(const winrt::hstring& localeName) const;
-#endif // defined(WINRT_BASE_H)
 
-#if defined(WINRT_BASE_H)
     winrt::hstring to_hstring(PCWSTR localeName) const;
 #endif // defined(WINRT_BASE_H)
 

From 30427b59979e0a5da113ab3561991f075bb6bea5 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Mon, 16 Jun 2025 02:02:07 -0700
Subject: [PATCH 09/10] Fixed some comments

---
 specs/decimal/decimal.md | 56 ++++++++++++++++++++--------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index c0c9100501..de60bf4371 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -453,8 +453,8 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT ("") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_string(PCSTR source, PCSTR localeName);
 
     /// Parse the string using the user's default locale.
@@ -475,8 +475,8 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_string(PCWSTR source, PCWSTR localeName);
 
     /// Parse the string using the user's default locale.
@@ -497,14 +497,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName=NULL for the invariant locale.
-    /// @note localeName="" for the user default locale.
+    /// @note localeName="" for the invariant locale.
+    /// @note localeName=NULL for the user default locale.
     static decimal from_string(const std::string& source, const std::string& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName=NULL for the invariant locale.
-    /// @note localeName="" for the user default locale.
+    /// @note localeName="" for the invariant locale.
+    /// @note localeName=NULL for the user default locale.
     static decimal from_string(const std::string& source, const PCSTR localeName);
 
     /// Parse the string using the user's default locale.
@@ -528,14 +528,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName=NULL for the invariant locale.
-    /// @note localeName="" for the user default locale.
+    /// @note localeName="" for the invariant locale.
+    /// @note localeName=NULL for the user default locale.
     static decimal from_string_view(const std::string_view& source, const std::string_view& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName=NULL for the invariant locale.
-    /// @note localeName="" for the user default locale.
+    /// @note localeName="" for the invariant locale.
+    /// @note localeName=NULL for the user default locale.
     static decimal from_string_view(const std::string_view& source, PCSTR localeName);
 
     /// Parse the string using the user's default locale.
@@ -559,14 +559,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_wstring(const std::wstring& source, const std::wstring& localeName);
 
     /// Parse the string using the user's default locale.
@@ -590,14 +590,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName);
 
     /// Parse the string using the user's default locale.
@@ -622,14 +622,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName);
 
     /// Parse the string using the user's default locale.
@@ -655,14 +655,14 @@ public:
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName);
 
     /// Parse the string using the specified locale.
     /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale.
+    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
+    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
     static decimal from_hstring(const winrt::hstring& source, PCWSTR localeName);
 
     /// Parse the string using the user's default locale.

From 24018a33efbadc4c9daf6e8f2ec1fdb3ede86971 Mon Sep 17 00:00:00 2001
From: Howard Kapustein <howardk@microsoft.com>
Date: Sat, 28 Jun 2025 19:35:00 -0700
Subject: [PATCH 10/10] Removed *string_view overloads as there's no good way
 for us to handle if not null-terminated (callers can handle it best)

---
 specs/decimal/decimal.md | 62 ----------------------------------------
 1 file changed, 62 deletions(-)

diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md
index de60bf4371..01b628a0be 100644
--- a/specs/decimal/decimal.md
+++ b/specs/decimal/decimal.md
@@ -519,37 +519,6 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_string(const std::string& source, PCSTR localeName, decimal& value);
 
-public:
-    /// Parse the string using the user's default locale.
-    static decimal from_string_view(const std::string_view& source);
-
-    /// Parse the string using the invariant locale.
-    static decimal from_string_view_invariant(const std::string_view& source);
-
-    /// Parse the string using the specified locale.
-    /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName="" for the invariant locale.
-    /// @note localeName=NULL for the user default locale.
-    static decimal from_string_view(const std::string_view& source, const std::string_view& localeName);
-
-    /// Parse the string using the specified locale.
-    /// @note localeName="!x-sys-default-locale" for the system default locale.
-    /// @note localeName="" for the invariant locale.
-    /// @note localeName=NULL for the user default locale.
-    static decimal from_string_view(const std::string_view& source, PCSTR localeName);
-
-    /// Parse the string using the user's default locale.
-    static bool try_from_string_view(const std::string_view& source, decimal& value);
-
-    /// Parse the string using the invariant locale.
-    static bool try_from_string_view_invariant(const std::string_view& source, decimal& value);
-
-    /// Parse the string using the specified locale.
-    static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value)
-
-    /// Parse the string using the specified locale.
-    static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value);
-
 public:
     /// Parse the string using the user's default locale.
     static decimal from_wstring(const std::wstring& source);
@@ -581,37 +550,6 @@ public:
     /// Parse the string using the specified locale.
     static bool try_from_wstring(const std::wstring& source, PCWSTR localeName, decimal& value);
 
-public:
-    /// Parse the string using the user's default locale.
-    static decimal from_wstring_view(const std::wstring_view& source);
-
-    /// Parse the string using the invariant locale.
-    static decimal from_wstring_view_invariant(const std::wstring_view& source);
-
-    /// Parse the string using the specified locale.
-    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
-    static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName);
-
-    /// Parse the string using the specified locale.
-    /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale.
-    /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale.
-    /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale.
-    static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName);
-
-    /// Parse the string using the user's default locale.
-    static bool try_from_wstring_view(const std::wstring_view& source, decimal& value);
-
-    /// Parse the string using the invariant locale.
-    static bool try_from_wstring_view_invariant(const std::wstring_view& source, decimal& value);
-
-    /// Parse the string using the specified locale.
-    static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value);
-
-    /// Parse the string using the specified locale.
-    static bool try_from_wstring_view(const std::wstring_view& source, PCWSTR localeName, decimal& value);
-
 public:
 #if defined(__hstring_h__) && defined(__WINSTRING_H_)
     /// Parse the string using the user's default locale.