Tuesday, November 22, 2016

Validate Two properties

to make sure one property change trigger the other property run validation logic,
must call OnVilidate Code into IDataErrorInfo type of logic in its property Setter

<TextBox Grid.Column="1" Text="{Binding ...,ValidatesOnDataErrors=True,NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextBoxWithValidationStyle}">


[MustBeGreaterLessThanAllowSuffix("TheOther", false, true, ErrorMessage = "Please specify ..")]

using System;

using System.ComponentModel.DataAnnotations;

using System.Linq;

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]

public class MustBeGreaterLessThanAllowSuffixAttribute : ValidationAttribute

{

public string CompareToPropertyName { get; private set; }

public bool Greater { get; private set; }

public bool IncludeEqual { get; private set; }

public object[] Values { get; private set; }

private static readonly char[] SUFFIXES = new char[4] { 'M', 'm', 'K', 'k' };

public MustBeGreaterLessThanAllowSuffixAttribute(string compareToPropertyName,bool greater,bool includeEqual, params object[] values)

{

CompareToPropertyName = compareToPropertyName;

Greater = greater;

IncludeEqual = includeEqual;

Values = values;

}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)

{

var compToProperty = validationContext.ObjectType.GetProperty(CompareToPropertyName);

var compToValue = compToProperty.GetValue(validationContext.ObjectInstance, null);

return VerifyValidGreaterThanCondition(value, compToValue) ? ValidationResult.Success : new ValidationResult(ErrorMessage);

}

private bool VerifyValidGreaterThanCondition(object value, object compToValue)

{

if (value == null || compToValue == null)

{

return true;

}

string valueNoSuffix = value.ToString().TrimEnd(SUFFIXES);

string compToValueNoSuffix = compToValue.ToString().TrimEnd(SUFFIXES);

double dValue, dCompToValue;

if (!double.TryParse(valueNoSuffix, out dValue) || !double.TryParse(compToValueNoSuffix, out dCompToValue))

{

return true;

}

var dValueMutiplied = dValue * GetMultiplier(value);

var dCompToValueMutiplied = dCompToValue * GetMultiplier(compToValue);

if (Greater)

{

return IncludeEqual ? dValueMutiplied >= dCompToValueMutiplied : dValueMutiplied > dCompToValueMutiplied;

}

return IncludeEqual ? dValueMutiplied <= dCompToValueMutiplied : dValueMutiplied < dCompToValueMutiplied;

}

private double GetMultiplier(object value)

{

if(value==null)

return 1.0;

char suffix = value.ToString().LastOrDefault();

switch (suffix)

{

case 'M':

case 'm':

return 1E6;

case 'K':

case 'k':

return 1E3;

}

return 1.0;

}



[CustomValidation(typeof(VegaTraderSettingValidator), "Check")]

using System.ComponentModel.DataAnnotations;

public class VegaTraderSettingValidator

{

public static ValidationResult Check(string s)

{

return ValidationResult.Success;

}

}



[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]

public class MutualExclusiveDataEntryAttribute : ValidationAttribute

{

public string MutualExclusivePropertyName { get; private set; }

public MutualExclusiveDataEntryAttribute(string mutualExclusivePropertyName)

{

MutualExclusivePropertyName = mutualExclusivePropertyName;

}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)

{

var mutProperty = validationContext.ObjectType.GetProperty(MutualExclusivePropertyName);

if (mutProperty == null)

return ValidationResult.Success;

var mutValue = mutProperty.GetValue(validationContext.ObjectInstance, null);

return VerifyMutualExclsivity(value, mutValue) ? ValidationResult.Success : new ValidationResult(ErrorMessage);

}

private bool VerifyMutualExclsivity(object value, object mutValue)

{

if (value == null || mutValue == null)

return true;

if (!value.IsDefault() && !mutValue.IsDefault())

return false;

return true;

}

}




Saturday, November 19, 2016

Attached Property based TextBox RegEx mask



                {
                    var localTxt = lastValidText;
                    var proposedText = GetProposedText(tbInstance, e1.Text);
                    if (!maskRegEx.IsMatch(proposedText))
                    {
                        e1.Handled = true;
                    }
                };
                
                tbInstance.Loaded += (s, e1) =>
                {
                    if (maskRegEx.IsMatch(tbInstance.Text))
                    {
                        lastValidText = tbInstance.Text;
                        SetHasRegExMisMatch(tbInstance,false);
                    }
                    else
                    {
                        SetHasRegExMisMatch(tbInstance, true);
                    }
                };

                tbInstance.TextChanged += (s, e1) =>
                {
                    if (maskRegEx.IsMatch(tbInstance.Text))
                    {
                        lastValidText = tbInstance.Text;
                        SetHasRegExMisMatch(tbInstance, false);
                    }
                    else
                    {
                        SetHasRegExMisMatch(tbInstance, true);
                    }
                };

                tbInstance.PreviewLostKeyboardFocus += (s, e1) =>
                {
                    var localTxt = lastValidText;
                    if (!maskRegEx.IsMatch(tbInstance.Text))
                    {
                        SetHasRegExMisMatch(tbInstance, true);
                        e1.Handled = true;
                        tbInstance.Text = localTxt;
                        tbInstance.CaretIndex = 99;
                    }
                    else
                    {
                        SetHasRegExMisMatch(tbInstance, false);
                    }
                };            
        }

        private static string GetProposedText(TextBox textBox, string newText)
        {
            var text = textBox.Text;

            if (textBox.SelectionStart != -1)
            {
                text = text.Remove(textBox.SelectionStart, textBox.SelectionLength);
            }

            text = text.Insert(textBox.CaretIndex, newText);

            return text;
        }
    }


C# implicit operator for conversion

implicit operator is conversion operator. 
  //Tuple with Parameter-Less Ctor to enable serialization
    [Serializable]
    public class Tuple2<T1, T2>
    {
        public Tuple2() { }

        public T1 Item1 { get; set; }
        public T2 Item2 { get; set; }

        public static implicit operator Tuple2<T1, T2>(Tuple<T1, T2> t)
        {
            return new Tuple2<T1, T2>()
            {
                Item1 = t.Item1,
                Item2 = t.Item2
            };
        }

        public static implicit operator Tuple<T1, T2>(Tuple2<T1, T2> t)
        {
            return Tuple.Create(t.Item1, t.Item2);
        }
    }

Tuesday, November 15, 2016

Using Pixel shader to highlight data grid row

/// <summary>
    /// Dev Express GridControl does not support multi selection when Master-Detail rows are involved. This behavior highlights multiple rows
    /// and persist onto ViewModel. So it has the effect of multiple selection.
    /// </summary>
    public class MultiRowHighlightBehavior : Behavior<GridControl>
    {

        #region properties

        public int MaxNumberOfRowsHighlighted
        {
            get { return (int)this.GetValue(MaxNumberOfRowsHighlightedProperty); }
            set { this.SetValue(MaxNumberOfRowsHighlightedProperty, value); }
        }
        public static readonly DependencyProperty MaxNumberOfRowsHighlightedProperty = DependencyProperty.Register(
          "MaxNumberOfRowsHighlighted", typeof(int), typeof(MultiRowHighlightBehavior), new PropertyMetadata(int.MaxValue));

        // use IList, INotifyCollectionChanged to avoid generic in DP def e.g. ObservableCollection<T>

        // Pass highlighted Data Rows to VM
        public IList ViewModelHighlightedRows
        {
            get { return (IList)this.GetValue(ViewModelHighlightedRowsProperty); }
            set { this.SetValue(ViewModelHighlightedRowsProperty, value); }
        }
        public static readonly DependencyProperty ViewModelHighlightedRowsProperty = DependencyProperty.Register(
          "ViewModelHighlightedRows", typeof(IList), typeof(MultiRowHighlightBehavior), new PropertyMetadata(null));

        // need to pass in Data Rows for the GridControl, so any removal triggers highlighting updates due to row position changes.
        public INotifyCollectionChanged ViewModelDataRows
        {
            get { return (INotifyCollectionChanged)this.GetValue(ViewModelDataRowsProperty); }
            set { this.SetValue(ViewModelDataRowsProperty, value); }
        }
        public static readonly DependencyProperty ViewModelDataRowsProperty = DependencyProperty.Register(
          "ViewModelDataRows", typeof(INotifyCollectionChanged), typeof(MultiRowHighlightBehavior), new PropertyMetadata(null));


        public string HighLightingColorHex
        {
            get { return (string)this.GetValue(HighLightingColorHexProperty); }
            set { this.SetValue(HighLightingColorHexProperty, value); }
        }
        public static readonly DependencyProperty HighLightingColorHexProperty = DependencyProperty.Register(
          "HighLightingColorHex", typeof(string), typeof(MultiRowHighlightBehavior), new PropertyMetadata(DefaultColorHex));


        public TableViewHitTest HighlightingClickArea
        {
            get { return (TableViewHitTest)this.GetValue(HighlightingClickAreaProperty); }
            set { this.SetValue(HighlightingClickAreaProperty, value); }
        }
        public static readonly DependencyProperty HighlightingClickAreaProperty = DependencyProperty.Register(
          "HighlightingClickArea", typeof(TableViewHitTest), typeof(MultiRowHighlightBehavior), new PropertyMetadata(TableViewHitTest.RowIndicator));


        public bool AllowHighLightingMasterRow
        {
            get { return (bool)this.GetValue(AllowHighLightingMasterRowProperty); }
            set { this.SetValue(AllowHighLightingMasterRowProperty, value); }
        }
        public static readonly DependencyProperty AllowHighLightingMasterRowProperty = DependencyProperty.Register(
          "AllowHighLightingMasterRow", typeof(bool), typeof(MultiRowHighlightBehavior), new PropertyMetadata(false));


        public bool UseShaderEffect
        {
            get { return (bool)this.GetValue(UseShaderEffectProperty); }
            set { this.SetValue(UseShaderEffectProperty, value); }
        }
        public static readonly DependencyProperty UseShaderEffectProperty = DependencyProperty.Register(
          "UseShaderEffect", typeof(bool), typeof(MultiRowHighlightBehavior), new PropertyMetadata(true));

        private const string DefaultColorHex = "#FF3D3D3D";
        private SolidColorBrush _highLightingBrush;


        private enum HighlightingState
        {
            On,
            Off
        }

        #endregion

        #region event

        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
            AssociatedObject.Loaded += AssociatedObject_Loaded;




            TrySetHighlightingBrush();
        }

        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            var sv = VisualTreeHelpers.FindChild<ScrollViewer>(AssociatedObject);
            if (sv != null)
            {
                sv.ScrollChanged += (s, _) => { if (ViewModelHighlightedRows.Count > 0) RedoHilighting(); };
            }
        }

        protected override void OnChanged()
        {
            base.OnChanged();
            if (ViewModelDataRows != null)
            {
                ViewModelDataRows.CollectionChanged += ViewModelDataRows_CollectionChanged;
            }
            if (ViewModelHighlightedRows is INotifyCollectionChanged)  // e.g ObservableCollection<T> is IList and INotifyCollectionChanged
            {
                (ViewModelHighlightedRows as INotifyCollectionChanged).CollectionChanged += ViewModelHighlightedRows_CollectionChanged;
            }
        }

        void ViewModelHighlightedRows_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (ViewModelHighlightedRows.Count == 0) RedoHilighting(); // clear all highlights if collection cleared by outside caller.
        }

        // Rows removed by VM will be removed from highlighted rows if present
        void ViewModelDataRows_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (var i in e.OldItems)
                {
                    if (ViewModelHighlightedRows != null) ViewModelHighlightedRows.Remove(i);
                }
                RedoHilighting();
            }
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                RedoHilighting();
            }
        }

        void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (AssociatedObject.View == null) return;
            var view = AssociatedObject.View as TableView;
            if (view == null) return;

            TableViewHitInfo hitInfo = view.CalcHitInfo(e.OriginalSource as DependencyObject);

            if (hitInfo == null) return;

            // Highlighting happens if user click on Row Header. So highlighting will not interfare with Row/Cell/Expander selection/expanding functionality
            if (hitInfo.HitTest == HighlightingClickArea)
            {
                var row = view.GetRowElementByMouseEventArgs(e) as GridRow;
                if (row == null || row.RowDataContent == null) return;
                var rowData = row.RowDataContent.DataContext as RowData;
                if (rowData == null || ViewModelHighlightedRows == null) return;

                if (!AllowHighLightingMasterRow && IsMasterRow(row) && !HasMarketDepth(rowData.Row)) return;  // use visual tree to check if row =master row, no API found

                if (ViewModelHighlightedRows.Contains(rowData.Row))
                {
                    ToggleHighlighting(row, HighlightingState.Off);
                    ViewModelHighlightedRows.Remove(rowData.Row);
                }
                else
                {
                    if (ViewModelHighlightedRows.Count >= MaxNumberOfRowsHighlighted) return;
                    ToggleHighlighting(row, HighlightingState.On);
                    ViewModelHighlightedRows.Add(rowData.Row);
                }
            }
        }

        private bool HasMarketDepth(object rowDataObject)
        {
            try
            {
                PropertyInfo propInfo = rowDataObject.GetType().GetProperty("HasMarketDepth", BindingFlags.Instance | BindingFlags.Public);

                if (propInfo != null)
                {
                    var val = propInfo.GetValue(rowDataObject, null);
                    return (bool)val;
                }
            }
            catch (Exception)
            {


            }
            return false;
        }

        #endregion

        #region change View and VM, etc.

        // change view only, not ViewModel
        private void ToggleHighlighting(GridRow row, HighlightingState hState)
        {
            try
            {
                var rowIndControl = VisualTreeHelpers.FindChild<RowIndicatorControl>(row);
                var ricBorder = VisualTreeHelpers.FindChild<Border>(rowIndControl);

                SolidColorBrush toggleBrush;
                Effect toggleEff;
                double toggleThickness;
                if (hState == HighlightingState.On)
                {
                    toggleBrush = _highLightingBrush;
                    toggleThickness = 1;
                    toggleEff = new ColorToneEffect() { DarkColor = Colors.Transparent, LightColor = Colors.LightBlue, ToneAmount = 0.1 };
                }
                else
                {
                    toggleBrush = new SolidColorBrush(Colors.Transparent);
                    toggleThickness = 0;
                    toggleEff = null;
                }

                var rowContentBorder = VisualTreeHelpers.FindChild<Border>(row, "RowContentBorder");
                var fixNoneCellstBorder = VisualTreeHelpers.FindChild<Border>(row, "PART_FixedNoneCellsBorder");
                var detailButtonBorder = VisualTreeHelpers.FindChild<Border>(row, "PART_DetailButtonBorder");

                if (UseShaderEffect)  // Shader effect will highlighting on top of all colors across a row
                {
                    ricBorder.Effect = toggleEff;
                    rowContentBorder.Effect = toggleEff;
                    fixNoneCellstBorder.Effect = toggleEff;
                    detailButtonBorder.Effect = toggleEff;
                }
                else
                {
                    ricBorder.Background = toggleBrush;
                    ricBorder.BorderThickness = new Thickness(toggleThickness, toggleThickness, 0, toggleThickness);
                    ricBorder.BorderBrush = toggleBrush;

                    rowContentBorder.BorderBrush = toggleBrush;
                    rowContentBorder.BorderThickness = new Thickness(0, toggleThickness, 0, toggleThickness < 0.5 ? 0.0 : 1.0);

                    fixNoneCellstBorder.BorderBrush = toggleBrush;
                    fixNoneCellstBorder.BorderThickness = new Thickness(0, toggleThickness, 0,
                        toggleThickness < 0.5 ? 0.0 : 1.0);

                    detailButtonBorder.BorderBrush = toggleBrush;
                    detailButtonBorder.BorderThickness = new Thickness(0, toggleThickness, 0, toggleThickness);
                }

            }
            catch (Exception)
            {


            }
        }

        private static bool IsMasterRow(GridRow row)
        {
            try
            {
                var masterRowExpandBorder = VisualTreeHelpers.FindChild<Border>(row, "PART_DetailButtonBorder");
                if (masterRowExpandBorder == null) return false;
                var isMasterRow = VisualTreeHelpers.FindChild<Grid>(masterRowExpandBorder) != null;
                return isMasterRow;
            }
            catch (Exception)
            {
                return false;  // if not sure, let user highlight and un-highlight
            }

        }

        void RedoHilighting()
        {
            if (AssociatedObject == null || AssociatedObject.View == null) return;
            var view = AssociatedObject.View as TableView;
            if (view == null) return;

            var hp = VisualTreeHelpers.FindChild<HierarchyPanel>(view);
            if (hp == null) return;

            AssociatedObject.RefreshData();
            foreach (var c in hp.Children)
            {
                var row = c as GridRow;
                if (row == null || row.RowDataContent == null) continue;
                var rowData = row.RowDataContent.DataContext as RowData;
                if (rowData == null) continue;

                if (ViewModelHighlightedRows.Contains(rowData.Row))
                {
                    ToggleHighlighting(row, HighlightingState.On);
                }
                else
                {
                    ToggleHighlighting(row, HighlightingState.Off);
                }
            }
        }

        private void TrySetHighlightingBrush()
        {
            try
            {
                _highLightingBrush = (new BrushConverter().ConvertFrom(HighLightingColorHex)) as SolidColorBrush;
            }
            catch (Exception)
            {
                _highLightingBrush = (new BrushConverter().ConvertFrom(DefaultColorHex)) as SolidColorBrush;

            }

            if (_highLightingBrush != null) _highLightingBrush.Freeze();
        }

        #endregion

    }

setup Eclipse CDT and optional in c++ 17

(1) create an empty project, cygwin gcc, all the include will be cygwin x86_64, no need to set include path in proj props
(2) set misc flag to have -std=c++17 (lower case)
(3) make sure tool chain editor set CDT internal builder
(4) ignore red squiggles and may rebuild C++ indexes.
(5) how to find C++ header file http://en.cppreference.com/w/cpp/header
(6) sometimes, include file still see "unresolved" error, e.g std::function in . This is caused by preprocessor
    proj->props->C++ general->Preprocessor..etc.->CDT gcc build-in Compiler Settings->uncheck use global, add -std=c++14

 #include <experimental\optional>

using namespace std;
using namespace std::experimental;

optional<pair<string,int>> to_roman(int n)
{
 if(n>10) return {{"X",n-20}};
 if(n>9) return {{"IX",n-9}};
 if(n>5) return {{"V",n-5}};
 if(n>4) return {{"IV",n-4}};
 if(n>1) return {{"I",n-1}};
 return nullopt;  // constexpr inside experimental\optional
}

Saturday, November 12, 2016

MSVC Cuda

(1) cuda is nvidia GPU heterogeneous parallel API integrated in vs 2015
(2) must turn on .net 3.5 window 10 features to compile
(3) search msvc cuda to download nvidia toolkit and vs integration
(4) Control panel, device manager, display adapter shows nvida 5200m for me and cuda capable
(5) must set Cuda/C++ device to Compute_20,sm_20 for NVS 5200M, my labtop cannot do CC=35.
(6) https://en.wikipedia.org/wiki/CUDA#Supported_GPUs list CC=compute capability
(7) can search Cuda.8.0.props file to change CodeGeneration tag to compute=35,sm=35 for all projects.
e.g.C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations
(8) <<<blockSz,WarpSz>>> host to device call with blkSz and Hardware thread size.
(9) __global__ kernel function run on device. __ldg __shfl_down needs 35 so my labtop too old
(10) grid + Block +warp, segments GPU hardware thread into 3-dim cubes. 

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>

cudaError_t full_Reduce(int *out, const int *in, size_t n);

__global__ void full_reduce_kernel(int *out, const int *in,size_t n)
{
 int sum = 0; // in hardware,it is a vector<int> width=32,init 0

 // a thread coming choose a block to start, only consider dim-x, y=z=1
 // 4= each thread process 4 elements
 size_t start = (threadIdx.x + blockIdx.x*blockDim.x) * 4; 

 for (size_t i = start; i < start+4 && i < n; i++)
 {
  sum += in[i]; //again i is vector of 32 addresses
  //sum += __ldg(in + i); //_ldg supported in 35, not 20 but NVS 5200M Compute Capability=2.1
 } 
 // shift of SIMD registers, 32 threads move data half by half to front, invalidate back half
 // __shfl_down support in 35, not 20
 /*sum += __shfl_down(sum, 16);
 sum += __shfl_down(sum, 8);
 sum += __shfl_down(sum, 4);
 sum += __shfl_down(sum, 2);
 sum += __shfl_down(sum, 1);*/
 __shared__ int shared_sum; //not vector
 shared_sum = 0;
 __syncthreads(); // only sync warp in a block
 if (threadIdx.x % 32 == 0)
  atomicAdd(&shared_sum, sum);
 __syncthreads();
 if (threadIdx.x == 0) // shfl_down will make only idx=0 valid
  atomicAdd(out, shared_sum);
}

int main()
{
 const int n = 5;
 const int in[n] = { 1,2,3,4,5 };
 int out[n] = { 0 };
 cudaError_t cudaStatus1 = full_Reduce(out, in, n);
 if (cudaStatus1 != cudaSuccess) {
  fprintf(stderr, "full reduce failed!");
  return 1;
 }

 printf("%d %d %d %d %d\n",out[0],out[1],out[2],out[3],out[4]);
 cudaStatus1 = cudaDeviceReset();
 return 0;
}

cudaError_t full_Reduce(int *out, const int *in, size_t n)
{
 int *dev_in = 0;
 int *dev_out = 0;
 int sz = n * sizeof(int);
 cudaError_t cudaStatus;

 cudaStatus = cudaSetDevice(0);

 cudaStatus = cudaMalloc((void**)&dev_out, sz);
 cudaStatus = cudaMalloc((void**)&dev_in, sz);

 cudaStatus = cudaMemcpy(dev_in, in, sz, cudaMemcpyHostToDevice);
 full_reduce_kernel<<<1,n>>>(dev_out, dev_in,n);  // call dev not int
 cudaStatus = cudaGetLastError();
 if (cudaStatus != cudaSuccess) {
  fprintf(stderr, "full redu kernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
  goto FreeDev;
 }

 cudaStatus = cudaDeviceSynchronize();
 cudaStatus = cudaMemcpy(out, dev_out, sz, cudaMemcpyDeviceToHost);

FreeDev:
 cudaFree(dev_out);
 cudaFree(dev_in);

 return cudaStatus;
}

Thursday, November 10, 2016

C++ threading Primitives:mutex, lock_guard, thread, async,future



#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <future>

using namespace std;

inline int f() { return 42; };
mutex m;

void access_shared_res()
{
 cout << " 1 thread in, endl cannot catch up" << endl;

 lock_guard<mutex> g(m);
 cout << " 1 thread passed " <<this_thread::get_id()<< endl;
 this_thread::sleep_for(chrono::seconds(5));
}

int main()
{
 cout << " main thread " << this_thread::get_id() << endl;
 thread  t1(access_shared_res);
 thread  t2(access_shared_res);
 t1.join();
 t2.join();

 std::future<int> f1 = std::async(std::launch::async, []() {return 8; });
 cout << f1.get() << endl;
 std::future<int> promise = std::async(std::launch::async, &f);
 cout << promise.get() << endl;

 std::string s;
 getline(cin, s);
    return 0;
}


Monday, November 7, 2016

Setup Behavior event of its dependency property and connect to the instance not static

Dependency Prop inside a behavior is static. So its event fires into a static event handler.
But the dependencyObject in the param is the hehavior instance and can call instance method.

       public static readonly DependencyProperty TradingLevelProperty = DependencyProperty.Register(
        "TradingLevel", typeof(TradingLevelTypes), typeof(NumericTextBoxCustomParamBehavior), new PropertyMetadata(TradingLevelTypes.Low, TradingLevelrPropertyChanged));

        public TradingLevelTypes TradingLevel
        {
            get { return (TradingLevelTypes)GetValue(TradingLevelProperty); }
            set { SetValue(TradingLevelProperty, value); }
        }



        private static void TradingLevelrPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var behaviorInstance = dependencyObject as NumericTextBoxCustomParamBehavior;
            if (behaviorInstance != null)
            {
                behaviorInstance.EnsureNonNullableDataVisibility();
            }
        }

        void EnsureNonNullableDataVisibility()
        {
            var scrollContentPresenter = AssociatedObject.FindChild("PART_ScrollContentPresenter");
            if (scrollContentPresenter != null)
            {
                scrollContentPresenter.Visibility=TradingLevel== TradingLevelTypes.ServerDefault? Visibility.Hidden: Visibility.Visible;
            }
        }

accessing optional by de-refence pointer


Eclipse CDT optional is in <experimental\optional> and IDE red squiggly line need to be ignored

p default to either false or default value like 0
*p =default 0 or *p=assigned value if has a value like 90

#include <iostream>
#include <vector>
#include <cstdlib>
#include <experimental\optional>

using namespace std;

int main() {

 std::experimental::optional<int> p;

        cout<<*p<<endl;
 if(!p)
  cout<<"not set"<<endl;

 if(p<=12)
  cout<<"compare to int p=0"<<endl;

 p=90;
 if(p)
 {
  cout<<"access value by* "<<*p<<endl;
 }

 return 0;
}

Sunday, November 6, 2016

iota and random shuffle

iota comes from "not an iota", meaning getting nothing out.
oppsitely, means init with some increasing sequence.
std::shuffle with mt19937 would get random segquence.
mt19937 is a typedef of complicated hex input param for Meresene-Tiwster pseudo random generator
std::random_device{}() is a random seed

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
#include <numeric>
#include <random>

using namespace std;

int main()
{
 vector<double> v(10);
 iota(v.begin(), v.end(), -1.1);
 for (auto n : v)
  cout << n << endl;
 cout << endl;
 shuffle(v.begin(),v.end(), std::mt19937{ std::random_device{}() });
 for (auto n : v)
  cout << n << endl;
 std::string s;
 getline(cin, s);
    return 0;
}



Gather since cannot slide into middle

1. Gather is to split at gather point and do two partitions.
2. partition put true in the front. So gather front partition needs not1
3. after partition, iter point to last_true+1. So two for-loop +- differs
4. not1 does work direction on lambda needs function
5. when gather point outside [be], it is a pure partition.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>

using namespace std;

template <class RI, typename Func>
auto gather(RI b, RI e, RI p, Func f)->pair<RI, RI>
{
 if (b < p && p < e)
 {
  return{ stable_partition(b, p, not1(function<bool(int i)>(f))),
   stable_partition(p, e, f) };
 }
};

int main()
{
 vector<int> v{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 };
 vector<int>::iterator p = v.begin() + 7;
 auto g=gather(v.begin(), v.end(), p, [](int i) {return i%2 == 0; });
 
 for (; g.first != p; ++g.first)
  cout << *g.first << endl;
 cout << "two parti met point" << endl;
 for(; g.second!=p;)
  cout << *--g.second << endl;

 std::string s;
 getline(cin, s);
    return 0;
}


Rotate and Slide

{1,2,3,4,5,6,7,8,9,10}
Rotate(f,m,l) f<m<l,moves [m,l) displace [f,m)=>[m,l)[f,m)
R(2,4,5)=R(f,m,l)=>{1,4,2,3,5...} 
 vector<int> v{ 1,2,3,4,5,6,7,8,9,10 };
 rotate(v.begin() + 1, v.begin() + 3, v.begin()+4);

Slide S(p,b,e)=[be)[pb)/S(b,e,p)=[ep)[be)
note pair construct differs to make pair.first= [be) iter

template <typename RI> //random forward iter
auto slide(RI b, RI e, RI p)->pair
{
 if (p < b)
 {
  return{ rotate(p,b,e),p };
 }
 if (e < p )
 {
  return{p, rotate(b, e, p) };
 }
 return{b,e};
};

int main()
{
 vector<int> v{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 };
 auto v1 = v, v2 = v, v3 = v;
 rotate(v1.begin() + 2, v1.begin() + 4, v1.begin()+5);
 auto p_s2 = slide(v2.begin() +6 , v2.begin() + 8, v2.begin() + 2);
 auto p_s11 = slide(v3.begin() + 6, v3.begin() + 8, v3.begin() + 11);
 cout << (*p_s2.first) << endl;
 cout << (*p_s2.second) << endl;

 cout << (*p_s11.first) << endl;
 cout << (*p_s11.second) << endl;

 std::string s;
 getline(cin, s);
    return 0;
}

Saturday, November 5, 2016

nth_element as percentile and std::copy vs std::move

= is simpler than std::copy, while std::move clear original vector. n
std::equal actually iterate through vector to compare.

note copy are needed since nth_element will shuffle elements in place.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
 vector<int> v{ 7,1,5,9,4,6,8,2,9,0,3 };
 vector<int> v_cp=v;
 //vector<int> v_cp(11);
 //std::copy(v.begin(), v.end(), v_cp.begin());
 cout << (equal(v.begin(), v.end(), v_cp.begin())?"true":"false")<< endl;
 vector<int> v_mv = std::move(v);
 cout << (equal(v_mv.begin(), v_mv.end(), v_cp.begin()) ? "true" : "false") << endl;

 const size_t pctil = v_cp.size()*0.75;
 nth_element(v_cp.begin(), v_cp.begin() + pctil, v_cp.end());
 cout <<"percentile elem="<< v_cp[pctil] << endl;

 v_cp.clear();
 cout << "sizes " << v.size() << " " << v_cp.size() << " " << v_mv.size() << endl;

 std::string s;
 getline(cin, s);
    return 0;
}

Generic Object Comparer

Object.Equals, IEqualalityComparer are actually not generic and the latter only used in Collection or LINQ like Contains.

This ObjectComparer is T, but does not consider reference type property.
The ignore will eliminate reference type and also those properties not to be considered in equality by users. so more flexible than Equals

    class ObjectComparer
    {
        public static bool PublicInstancePropertiesEquals<T>( T self, T to, params string[] ignore) where T : class
        {
            if (self != null && to != null)
            {
                var type = typeof(T);
                var ignoreList = new List<string>(ignore);
                var allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (var p in allProperties)
                {
                    if (!ignoreList.Contains(p.Name))
                    {
                        var selfValue = type.GetProperty(p.Name).GetValue(self, null);
                        var toValue = type.GetProperty(p.Name).GetValue(to, null);

                        if ((selfValue==null && toValue!=null) || (selfValue != null && !selfValue.Equals(toValue)))
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
            return self == to;
        }
    }

partition_copy has front back container

partition got a itr point to the begin of back partition, but it is not incrementable.
partition_copy allows pass in two containers through back/front_insert so can increment.
Note that vector is random iter but cannot use front_insert, why?
Note Stable Partition keep tag1 partition "Stabilize" and then partition by tag2 the back container


#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
#include <list>

using namespace std;

enum  attrib
{
 a0,a1, a2, a3, a4, a5, a6, a7, a8, a9,
 tag1 = a4,
 tag2 = a7
};

struct Entity
{
 attrib EntityAttrib;
};


int main()
{
 vector<Entity> v = { {a7},{ a1 }, { a5 }, { a9 }, { a4 }, { a6 }, { a8 }, { a2 }, { a3 }, {a0} };

 auto parti_tag1_itr=partition(v.begin(), v.end(), [](const Entity& e) {return e.EntityAttrib < tag1; });
 int c_front = count_if(v.begin(), v.end(), [](const Entity& e) {return e.EntityAttrib < tag1; });

 for(int i=0;i<c_front;i++)
     cout << (*(--parti_tag1_itr)).EntityAttrib << endl;
 cout << endl;

 vector<Entity> front_parti(10);
 list<Entity> back_parti(10);
 partition_copy(v.begin(), v.end(), back_inserter(front_parti), front_inserter(back_parti), [](const Entity& e) {return e.EntityAttrib > tag1; });

 for (auto e : front_parti)
 {
  cout << e.EntityAttrib << endl;
 }

 std::string s;
 getline(cin, s);
    return 0;
} 

stable_partition(back_parti.begin(), back_parti.end(), [](const Entity& e) {return e.EntityAttrib < tag2; });

Wednesday, November 2, 2016

sort partial_sort and stable and copy sementics

(1) Sort is the starting algo, stable means keep previous order so it only follows
(2) back_inserter convert object to an iterator.
(3) partition move true item in a container to front. false to back.
(4) partial/partition_copy moves and output two iterators.
(5) partial_sort means take 8 and sort until find top 5. so out_copy would be size 5

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>

using namespace std;

struct Person
{
 string FirstName;
 string MiddleName;
 string LastName;
};

int main()
{
 vector<Person> v{ {"Jason","P","Pierepaul"},{"Rob","C","Nokowich"},{"Jane","X","Smith"},{"Joe","A","Smith" }};

 sort(v.begin(), v.end(), [](const Person& a, const Person& b) {return a.MiddleName < b.MiddleName; });
 stable_sort(v.begin(), v.end(), [](const Person& a, const Person& b) {return a.FirstName<b.FirstName; });
 stable_sort(v.begin(), v.end(), [](const Person& a, const Person& b) {return a.LastName<b.LastName; });

 vector<int> v2 = { 42,17,89,22,34,78,63,12,57,99 };
 partial_sort(v2.begin(), v2.begin() + 5, v2.begin() + 8, greater<int>());

 vector<int> out_copy(5);
 partial_sort_copy(v2.begin(), v2.begin()+8, out_copy.begin(), out_copy.end(),greater<int>());

 vector<int> v3 = { 12,89,31,18,7,72,69,50,49,50,51,49 };
 vector<int>::iterator parti_itr = partition(v3.begin(), v3.end(), [](const int i) { return i < 50; });

 vector<int> true_parti, false_parti;
 partition_copy(v3.begin(), v3.end(), back_inserter(true_parti), back_inserter(false_parti), [](const int i) {return i < 50; });


 std::string s;
 getline(cin, s);
    return 0;
}


Tuesday, November 1, 2016

async void vs async task behave different


(1) for async-void, 2nd resume will never happen. 1st resume does happen
(2) for async-Task, both resume will not happen.

So async-void does not block Event Handler, but itself will be blocked forever
async-task Both event handler and itself will be blocked.
In both cases, UI is responsive=> There is a suspension point and UI return to do other things.
But resume gets affected

       private async void button_Click(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine("thread id:{0}", Thread.CurrentThread.ManagedThreadId);
          // m();
            await mT();
            Debug.WriteLine("Resume 1");
        }

        async void m()
        {
            Debug.WriteLine("thread id:{0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Run(() => {
                Debug.WriteLine("thread id:{0}",Thread.CurrentThread.ManagedThreadId);
                for (;;) { }
            });
            Debug.WriteLine("Resume 2");
        }

        async Task mT()
        {
            Debug.WriteLine("thread id:{0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Run(() => {
                Debug.WriteLine("thread id:{0}", Thread.CurrentThread.ManagedThreadId);
                for (;;) { }
            });
            Debug.WriteLine("Resume 2");
        }