1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
#include "pch.h"
#include "Class1.h"
#include <ppltasks.h>
#include <concurrent_vector.h>
using namespace concurrency;
using namespace Platform::Collections;
using namespace Windows::Foundation::Collections;
using namespace Windows::Foundation;
using namespace Windows::UI::Core;
using namespace UwpTestWinRtComponentCpp;
using namespace Platform;
Class1::Class1()
{
}
//Public API
IVector<double>^ Class1::ComputeResult(double input)
{
// Implement your function in ISO C++ or
// call into your C++ lib or DLL here. This example uses AMP.
float numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 10000.0 };
array_view<float, 1> logs(6, numbers);
// See http://msdn.microsoft.com/en-us/library/hh305254.aspx
parallel_for_each(
logs.extent,
[=](index<1> idx) restrict(amp)
{
logs[idx] = concurrency::fast_math::log10(logs[idx]);
}
);
// Return a Windows Runtime-compatible type across the ABI
auto res = ref new Vector<double>();
int len = safe_cast<int>(logs.extent.size());
for (int i = 0; i < len; i++)
{
res->Append(logs[i]);
}
// res is implicitly cast to IVector<double>
return res;
}
// Determines whether the input value is prime.
bool Class1::is_prime(int n)
{
if (n < 2)
return false;
for (int i = 2; i < n; ++i)
{
if ((n % i) == 0)
return false;
}
return true;
}
// This method computes all primes, orders them, then returns the ordered results.
IAsyncOperationWithProgress<IVector<int>^, double>^ Class1::GetPrimesOrdered(int first, int last)
{
return create_async([this, first, last]
(progress_reporter<double> reporter) -> IVector<int>^ {
// Ensure that the input values are in range.
if (first < 0 || last < 0) {
throw ref new InvalidArgumentException();
}
// Perform the computation in parallel.
concurrent_vector<int> primes;
long operation = 0;
long range = last - first + 1;
double lastPercent = 0.0;
parallel_for(first, last + 1, [this, &primes, &operation,
range, &lastPercent, reporter](int n) {
// Increment and store the number of times the parallel
// loop has been called on all threads combined. There
// is a performance cost to maintaining a count, and
// passing the delegate back to the UI thread, but it's
// necessary if we want to display a determinate progress
// bar that goes from 0 to 100%. We can avoid the cost by
// setting the ProgressBar IsDeterminate property to false
// or by using a ProgressRing.
if (InterlockedIncrement(&operation) % 100 == 0)
{
reporter.report(100.0 * operation / range);
}
// If the value is prime, add it to the local vector.
if (is_prime(n)) {
primes.push_back(n);
}
});
// Sort the results.
std::sort(begin(primes), end(primes), std::less<int>());
reporter.report(100.0);
// Copy the results to a Vector object, which is
// implicitly converted to the IVector return type. IVector
// makes collections of data available to other
// Windows Runtime components.
return ref new Vector<int>(primes.begin(), primes.end());
});
}
// This method returns no value. Instead, it fires an event each time a
// prime is found, and passes the prime through the event.
// It also passes progress info.
IAsyncActionWithProgress<double>^ Class1::GetPrimesUnordered(int first, int last)
{
auto window = Windows::UI::Core::CoreWindow::GetForCurrentThread();
m_dispatcher = window->Dispatcher;
return create_async([this, first, last](progress_reporter<double> reporter) {
// Ensure that the input values are in range.
if (first < 0 || last < 0) {
throw ref new InvalidArgumentException();
}
// In this particular example, we don't actually use this to store
// results since we pass results one at a time directly back to
// UI as they are found. However, we have to provide this variable
// as a parameter to parallel_for.
concurrent_vector<int> primes;
long operation = 0;
long range = last - first + 1;
double lastPercent = 0.0;
// Perform the computation in parallel.
parallel_for(first, last + 1,
[this, &primes, &operation, range, &lastPercent, reporter](int n)
{
// Store the number of times the parallel loop has been called
// on all threads combined. See comment in previous method.
if (InterlockedIncrement(&operation) % 100 == 0)
{
reporter.report(100.0 * operation / range);
}
// If the value is prime, pass it immediately to the UI thread.
if (is_prime(n))
{
// Since this code is probably running on a worker
// thread, and we are passing the data back to the
// UI thread, we have to use a CoreDispatcher object.
m_dispatcher->RunAsync(CoreDispatcherPriority::Normal,
ref new DispatchedHandler([this, n, operation, range]()
{
this->primeFoundEvent(n);
}, Platform::CallbackContext::Any));
}
});
reporter.report(100.0);
});
}
|