/// <summary> /// 함수의 [a,b] 구간을 적분합니다. /// </summary> /// <param name="func">적분할 함수</param> /// <param name="a">적분 시작 위치</param> /// <param name="b">적분 끝 위치</param> /// <returns>적분 값</returns> public override double Integrate(Func<double, double> func, double a, double b) { func.ShouldNotBeNull("func"); if(IsDebugEnabled) log.Debug(@"사다리꼴 적분법(Trapizoidal)을 이용하여 적분을 수행합니다. func=[{0}], a=[{1}], b=[{2}]", func, a, b); func.ShouldNotBeNull("func"); if(a > b) MathTool.Swap<double>(ref a, ref b); double result = 0; int n = GetSteps(a, b); double h = (b - a) / n; double x = a; Parallel.For(1, n, () => 0.0, (i, loopState, local) => local + func(a + h * i), local => { lock(_syncLock) result += local; }); //for(int i = 1; i < n; i++) //{ // x += h; // result += func(x); //} result = h * ((func(a) + func(b)) / 2 + result); if(IsDebugEnabled) log.Debug(@"적분결과=[{0}]", result); return result; }
/// <summary> /// 지정된 Function을 수행합니다. /// </summary> /// <param name="tryFunc">수행할 action</param> /// <param name="exceptionAction">예외 시 수행할 action</param> /// <param name="finallyAction">뒷처리를 위한 action</param> /// <param name="valueFactory">예외 시 반환할 기본 값을 생성하는 Factory</param> public static T TryFunction <T>(Func <T> tryFunc, Func <T> valueFactory = null, Action <Exception> exceptionAction = null, Action finallyAction = null) { tryFunc.ShouldNotBeNull("tryFunc"); try { return(tryFunc()); } catch (Exception ex) { if (exceptionAction != null) { exceptionAction(ex); } else { if (log.IsWarnEnabled) { log.Warn("작업 중에 예외가 발생했습니다만 무시합니다."); log.Warn(ex); } } } finally { if (finallyAction != null) { finallyAction(); } } return((valueFactory != null) ? valueFactory() : default(T)); }
/// <summary> /// Samples a function equidistant within the provided interval. /// </summary> /// <param name="function">The real-domain function to sample.</param> /// <param name="intervalBegin">The real domain interval begin where to start sampling.</param> /// <param name="intervalEnd">The real domain interval end where to stop sampling.</param> /// <param name="sampleCount">The number of samples to generate.</param> /// <param name="samplePoints">The real domain points where the samples are taken at.</param> /// <typeparam name="T">The value type of the function to sample.</typeparam> /// <returns>The generated sample vector.</returns> /// <exception cref="ArgumentNullException" /> /// <exception cref="ArgumentOutOfRangeException" /> public static T[] EquidistantInterval <T>(Func <double, T> function, double intervalBegin, double intervalEnd, int sampleCount, out double[] samplePoints) { function.ShouldNotBeNull("function"); sampleCount.ShouldBePositiveOrZero("sampleCount"); if (sampleCount == 0) { samplePoints = new double[0]; return(new T[0]); } if (sampleCount == 1) { samplePoints = new double[] { (intervalBegin + intervalEnd) / 2.0 }; return(new T[] { function(samplePoints[0]) }); } var step = (intervalEnd - intervalBegin) / (sampleCount - 1); samplePoints = PLinqTool.Generate(sampleCount, i => intervalBegin + i * step).ToArray(); samplePoints[samplePoints.Length - 1] = intervalEnd; var result = samplePoints .AsParallel() .AsOrdered() .Select(x => function(x)) .ToArray(); result[result.Length - 1] = function(intervalEnd); return(result); }
/// <summary> /// 정렬이 되었다면, 지정된 갯수의 최상위 요소중 <paramref name="count"/> 수만큼 반환합니다. /// </summary> /// <typeparam name="TSource">요소의 수형</typeparam> /// <typeparam name="TKey">요소 비교를 위한 Key의 수형</typeparam> /// <param name="source">요소 집합</param> /// <param name="keySelector">요소로부터 Key를 추출하는 Selector</param> /// <param name="count">취할 요소의 수</param> /// <returns></returns> public static IEnumerable <TSource> TakeTop <TSource, TKey>(this ParallelQuery <TSource> source, Func <TSource, TKey> keySelector, int count = 1) { keySelector.ShouldNotBeNull("keySelector"); if (IsDebugEnabled) { log.Debug("최상의 요소 중 [{0}]만큼 열거합니다.", count); } var comparer = new DescendingDefaultComparer <TKey>(); return (source.Aggregate(() => new SortedTopN <TKey, TSource>(count, comparer), (accum, item) => { accum.Add(keySelector(item), item); return accum; }, (accum1, accum2) => { foreach (var item in accum2) { accum1.Add(item); } return accum1; }, accum => accum.Values)); }
/// <summary> /// 여러 단계의 매핑을 거쳐야 할 때, 매핑함수 chain을 만들도록 해준다. /// </summary> /// <typeparam name="TNextOutput"></typeparam> /// <param name="nextFunc"></param> /// <param name="degreeOfParallelism"></param> /// <returns></returns> public Pipeline <TInput, TNextOutput> Next <TNextOutput>(Func <TOutput, TNextOutput> nextFunc, int degreeOfParallelism = 1) { nextFunc.ShouldNotBeNull("nextFunc"); degreeOfParallelism.ShouldBePositive("degreeOfParallelism"); return(new InternalPipeline <TNextOutput>(this, nextFunc, degreeOfParallelism)); }
/// <summary> /// 컬럼명=속성명 매핑함수를 이용하여 지정된 DataReader의 컬럼명을 속성명으로 매핑한다. /// </summary> /// <param name="reader">instance of IDataReader</param> /// <param name="mappingFunc">mapping function</param> /// <param name="propertyNamesToExclude">매핑에서 제외할 속성명</param> /// <returns>instance of <see cref="INameMap"/></returns> public static INameMap Mapping(this IDataReader reader, Func<string, string> mappingFunc, params string[] propertyNamesToExclude) { reader.ShouldNotBeNull("reader"); mappingFunc.ShouldNotBeNull("mappingFunc"); if(IsDebugEnabled) log.Debug("지정된 DataReader의 컬럼명을 속성명으로 매핑합니다..."); var nameMap = new NameMap(); var excludeNames = (propertyNamesToExclude != null) ? propertyNamesToExclude.ToList() : new List<string>(); for(int i = 0; i < reader.FieldCount; i++) { var columnName = reader.GetName(i); if(columnName.IsNotWhiteSpace()) { var propertyName = mappingFunc(columnName); if(propertyName.IsNotWhiteSpace() && excludeNames.Contains(propertyName, StringComparer.Ordinal) == false) nameMap.Add(columnName, propertyName); } } if(IsDebugEnabled) log.Debug("컬럼명-속성명 매핑 결과 = " + nameMap.CollectionToString()); return nameMap; }
/// <summary> /// <paramref name="table"/>의 정보를 Persistent object로 변환하여 제공합니다. /// </summary> /// <typeparam name="T">Persistent object 의 수형</typeparam> /// <param name="table"><see cref="DataTable"/></param> /// <param name="rowMapper">매핑 함수</param> /// <param name="firstResult">Persistent object를 만들 첫번째 레코드 인덱스 (0부터 시작)</param> /// <param name="maxResults">Persistent object를 만들 최대 레코드 수 (0이거나 null이면 DataReader 끝까지)</param> /// <returns>Persistent object의 컬렉션</returns> public static IList <T> Map <T>(this DataTable table, Func <DataRow, T> rowMapper, int firstResult = 0, int maxResults = 0) { table.ShouldNotBeNull("table"); rowMapper.ShouldNotBeNull("rowMapper"); if (IsDebugEnabled) { log.Debug("Mapping Function를 이용하여 DataTable로부터 [{0}] 수형의 객체를 생성합니다. firstResult=[{1}], maxResults=[{2}]", typeof(T).Name, firstResult, maxResults); } var firstCount = Math.Max(0, firstResult); var maxCount = maxResults; if (maxCount <= 0) { maxCount = Int32.MaxValue; } return (table.Rows .Cast <DataRow>() .Skip(firstCount) .Take(maxCount) .Select(rowMapper) .ToList()); }
/// <summary> /// y = func(x) 함수의 [lower, upper] 구간에 대해, 근을 찾는다 ( func(x) = 0 인 x 값 ) /// </summary> /// <param name="func">근을 찾을 함수</param> /// <param name="lower">근을 찾을 구간의 하한</param> /// <param name="upper">근을 찾을 구간의 상한</param> /// <param name="tryCount">시도 횟수</param> /// <param name="tolerance">근의 오차허용범위</param> /// <returns>근에 해당하는 x 값. 해를 못찾으면 <see cref="double.NaN"/>을 반환한다.</returns> public override double FindRoot(Func<double, double> func, double lower, double upper, int tryCount = MathTool.DefaultTryCount, double tolerance = MathTool.Epsilon) { func.ShouldNotBeNull("func"); tolerance = Math.Abs(tolerance); if(IsDebugEnabled) log.Debug(@"Find root by NewtonRapson... func=[{0}], lower=[{1}], upper=[{2}], tryCount=[{3}], tolerance=[{4}]", func, lower, upper, tryCount, tolerance); if(tryCount < DefaultTryCount) tryCount = DefaultTryCount; double x = (lower + upper) / 2; if(Math.Abs(func(x).Clamp(RootY, tolerance) - RootY) < double.Epsilon) return x; for(int i = 0; i < tryCount; i++) { double prevX = x; x -= func(x) / gfunc(func, x); if(IsDebugEnabled) log.Debug(@"root value=[{0}]", x); if(Math.Abs(x - prevX) < Math.Abs(prevX) * tolerance) return x; } return double.NaN; }
/// <summary> /// Computes a sequential exclusive prefix scan over the array using the specified function. /// </summary> public static void ExclusiveScanInPlaceSerial <T>(T[] array, Func <T, T, T> function, int fromInclusive, int toExclusive) { array.ShouldNotBeEmpty("array"); function.ShouldNotBeNull("function"); if (IsDebugEnabled) { log.Debug("순차방식의 배타적 스캔을 시작합니다... fromInclusive={0}, toExclusive={1}", fromInclusive, toExclusive); } var total = array[fromInclusive]; array[fromInclusive] = default(T); for (var i = fromInclusive + 1; i < toExclusive; i++) { var prevTotal = total; total = function(total, array[i]); if (IsDebugEnabled) { log.Debug("순차방식 ExclusiveScan... array[{0}]={1}, total={2}", i, array[i], total); } array[i] = prevTotal; } }
/// <summary> /// 비동기 방식의 작업을 수행할 때 예외처리를 담당해 줍니다. 비동기 방식 작업을 수행할 때에는 이 함수를 호출하시기 바랍니다. /// </summary> /// <param name="asyncFunc">비동기 방식 작업을 수행하는 Function</param> /// <param name="valueFactory">함수 실행 실패 시의 반환할 값 생성 함수</param> /// <param name="ageAction">예외 처리를 담당하는 Action</param> /// <param name="finallyAction">Finally Block 처리를 담당하는 Action</param> /// <returns>함수 반환 값</returns> public static T TryFunctionAsync <T>(Func <T> asyncFunc, Func <T> valueFactory = null, Action <AggregateException> ageAction = null, Action finallyAction = null) { asyncFunc.ShouldNotBeNull("asyncFunc"); try { return(asyncFunc()); } catch (AggregateException age) { if (ageAction != null) { ageAction(age); } else { if (log.IsErrorEnabled) { log.Error("비동기 작업 함수 실행 시 AggregateException 예외가 발생했습니다!!!"); log.Error(age.Flatten()); } age.Handle(ex => false); } } finally { if (finallyAction != null) { finallyAction(); } } return((valueFactory != null) ? valueFactory() : default(T)); }
/// <summary> /// <paramref name="millisecondsDelayed"/> 이후에 <paramref name="function"/>을 수행하는 작업을 생성합니다. /// </summary> /// <typeparam name="TResult">작업 결과 수형</typeparam> /// <param name="factory">Task Factory</param> /// <param name="millisecondsDelayed">실행 전에 지연할 시간(밀리초)</param> /// <param name="function">실행할 함수</param> /// <param name="cancellationToken">작업 취소용 토큰</param> /// <param name="creationOptions">작업 생성 옵션</param> /// <param name="scheduler">작업 스케쥴러</param> /// <returns>일정 시간 이후에 함수를 실행하는 작업</returns> public static Task <TResult> StartNewDelayed <TResult>(this TaskFactory <TResult> factory, int millisecondsDelayed, Func <TResult> function, CancellationToken?cancellationToken = null, TaskCreationOptions?creationOptions = null, TaskScheduler scheduler = null) { factory.ShouldNotBeNull("factory"); millisecondsDelayed.ShouldBePositiveOrZero("millisecondsDelayed"); function.ShouldNotBeNull("function"); scheduler = scheduler ?? factory.GetTargetScheduler(); if (IsDebugEnabled) { log.Debug("일정 시간 이후에 지정한 함수를 수행하는 작업을 생성합니다. 작업지연 시간=[{0}] msecs", millisecondsDelayed); } var tcs = new TaskCompletionSource <object>(); var timer = new Timer(obj => ((TaskCompletionSource <object>)obj).SetResult(null), tcs, millisecondsDelayed, Timeout.Infinite); return(tcs.Task.ContinueWith(_ => { timer.Dispose(); return function(); }, cancellationToken ?? factory.CancellationToken, ContinuationOptionsFromCreationOptions(creationOptions ?? factory.CreationOptions), scheduler)); }
public Pareto(double scale, double shape, Func <Random> randomFactory = null) { SetParameters(scale, shape); randomFactory.ShouldNotBeNull("randomFactory"); _random = randomFactory(); }
/// <summary> /// <see cref="ExecuteInstance{T}(IAdoRepository,INameMapper,System.Data.Common.DbCommand,IAdoParameter[])"/> 를 비동기적으로 수행하여, /// DataReader로부터 T 수형의 인스턴스를 매핑한다. /// </summary> /// <typeparam name="T">결과 셋으로 표현할 엔티티의 수형</typeparam> /// <param name="repository"><see cref="IAdoRepository"/></param> /// <param name="nameMapper">DataReader 컬럼과 엔티티의 속성명의 Name 매퍼</param> /// <param name="targetFactory">대상 객체 생성 함수</param> /// <param name="firstResult">첫번째 레코드 인덱스 (0부터 시작)</param> /// <param name="maxResults">최대 레코드 갯수(0이면 끝까지)</param> /// <param name="additionalMapping">추가적인 매핑 함수</param> /// <param name="query">실행할 SQL문 또는 Procedure Name</param> /// <param name="parameters">패러미터</param> /// <returns>매핑한 엔티티 컬렉션을 결과값으로 가지는 Task</returns> public static Task <IList <T> > ExecuteInstanceAsParallelAsync <T>(this IAdoRepository repository, INameMapper nameMapper, Func <T> targetFactory, int firstResult, int maxResults, Action <AdoResultRow, T> additionalMapping, string query, params IAdoParameter[] parameters) { nameMapper.ShouldNotBeNull("nameMapper"); targetFactory.ShouldNotBeNull("targetFactory"); query.ShouldNotBeWhiteSpace("query"); if (IsDebugEnabled) { log.Debug("비동기적으로 ExecuteReader()을 수행하고, 병렬로 매핑하여 결과를 IList<{0}>으로 매핑합니다... " + "query=[{1}], firstResult=[{2}], maxResults=[{3}]", typeof(T).Name, query, firstResult, maxResults); } return (Task.Factory .StartNew(() => { using (var reader = repository.ExecuteReader(query, parameters)) return reader.MapAsParallel <T>(targetFactory, nameMapper, firstResult, maxResults, additionalMapping); })); }
/// <summary> /// TInput 수형의 시퀀스를 매핑 함수를 통해 TOutput 시퀀스로 변환합니다. /// </summary> public static IEnumerable <TOutput> Map <TInput, TOutput>(this IEnumerable <TInput> inputs, Func <TInput, TOutput> mapping) { inputs.ShouldNotBeNull("inputs"); mapping.ShouldNotBeNull("mapping"); return(inputs.Select(mapping)); }
/// <summary> /// 비동기적으로 ExecuteReader()을 수행하고, 병렬 방식으로 매핑하여 결과를 IPageList{T} 으로 반환하는 Task를 빌드합니다 /// </summary> /// <typeparam name="T">결과 셋으로 표현할 엔티티의 수형</typeparam> /// <param name="repository"><see cref="IAdoRepository"/></param> /// <param name="rowMapFunc">DataReader로부터 {T} 수형의 인스턴스로 변환하는 메소드</param> /// <param name="query">실행할 SQL문 또는 Procedure Name</param> /// <param name="pageIndex">결과셋의 Page Index (0부터 시작)</param> /// <param name="pageSize">결과셋 Paging 시의 Page Size</param> /// <param name="parameters">패러미터</param> /// <returns>매핑한 엔티티 컬렉션을 결과값으로 가지는 Task</returns> public static Task <IPagingList <T> > ExecuteInstanceAsParallelAsync <T>(this IAdoRepository repository, Func <AdoResultRow, T> rowMapFunc, string query, int pageIndex, int pageSize, params IAdoParameter[] parameters) { rowMapFunc.ShouldNotBeNull("converter"); query.ShouldNotBeWhiteSpace("query"); if (IsDebugEnabled) { log.Debug("비동기적으로 ExecuteReader()을 수행하고, 병렬 방식으로 매핑하여 결과를 IPageList<{0}>으로 반환하는 Task를 빌드합니다... " + @"query=[{1}]", typeof(T).Name, query); } var itemsTask = Task.Factory.StartNew(() => { using (var reader = repository.ExecuteReader(query, parameters)) return(reader.MapAsParallel <T>(rowMapFunc, pageIndex * pageSize, pageSize)); }); var totalItemCountTask = repository.CountAsync(query, parameters); var result = new PagingList <T>(itemsTask.Result, pageIndex, pageSize, totalItemCountTask.Result); return(Task.Factory.FromResult((IPagingList <T>)result)); }
/// <summary> /// Depth-First Scan for Adjacent Graph /// </summary> /// <typeparam name="T">탐색할 Node의 수형</typeparam> /// <param name="source">Graph의 시작 Point</param> /// <param name="getAdjacent">현재 Node와 연결된 인접한 노드들을 찾아주는 함수</param> /// <returns>Depth-Firth Algorithm으로 탐색한 노드들의 컬렉션</returns> public static IEnumerable <T> GraphDepthFirstScan <T>(this T source, Func <T, IEnumerable <T> > getAdjacent) { source.ShouldNotBeNull("source"); getAdjacent.ShouldNotBeNull("getAdjacent"); var toScan = new Stack <T>(new[] { source }); var scanned = new HashSet <T>(); while (toScan.Count > 0) { T current = toScan.Pop(); yield return(current); scanned.Add(current); foreach (T item in getAdjacent(current)) { if (scanned.Contains(item) == false) { toScan.Push(item); } } } }
/// <summary> /// 계층 구조 순서대로 Scan을 수행한다. /// </summary> /// <typeparam name="T">Scan할 요소의 수형</typeparam> /// <param name="source">Scan 대상</param> /// <param name="startWith">계층 구조에서 시작할 위치를 지정해주는 함수 (보통 계층구조상의 Root 요소를 반환하는 함수)</param> /// <param name="connectBy">첫번째 요소가 두번째 요소의 부모인지 판단하는 함수 (두 요소사이에 계층구조가 있음을 파악한다)</param> /// <param name="canYieldLevel">계층구조상의 지정된 Level 정보를 반환할 것인가를 결정하는 함수</param> /// <param name="parent">부모 노드</param> /// <returns>계층 구조상의 순서대로 제공되는 리스트</returns> public static IEnumerable <Node <T> > ByHierarchy <T>(this IEnumerable <T> source, Func <T, bool> startWith, Func <T, T, bool> connectBy, Func <int, bool> canYieldLevel = null, Node <T> parent = null) { source.ShouldNotBeNull("source"); startWith.ShouldNotBeNull("startWith"); connectBy.ShouldNotBeNull("connectBy"); canYieldLevel = canYieldLevel ?? (_ => true); var level = (parent == null) ? 0 : parent.Level + 1; var items = source.Where(startWith); foreach (var item in items) { var newNode = new Node <T>(level, parent, item); if (canYieldLevel(level)) { yield return(newNode); } var item1 = item; foreach (var childNode in ByHierarchy <T>(source, possibleChild => connectBy(item1, possibleChild), connectBy, canYieldLevel, newNode)) { yield return(childNode); } } }
/// <summary> /// SharedCache에 해당 키에 해당하는 값이 있으면 그 값을 반환하고, 없으면, <paramref name="valueFactory"/>로 값을 생성해서 값을 저장 후 그 값을 반환합니다. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="sharedCache"></param> /// <param name="key"></param> /// <param name="valueFactory"></param> /// <returns></returns> public static T GetOrAdd <T>(this IndexusProviderBase sharedCache, string key, Func <T> valueFactory) { sharedCache.ShouldNotBeNull("sharedCache"); key.ShouldNotBeWhiteSpace("key"); valueFactory.ShouldNotBeNull("valueFactory"); if (IsDebugEnabled) { log.Debug("SharedCache에서 Key[{0}]에 해당하는 값을 로드합니다.", key); } T result; if (sharedCache.TryGet <T>(key, out result)) { return(result); } result = valueFactory(); if (sharedCache.TryAdd(key, result)) { return(result); } throw new InvalidOperationException(string.Format("ShardCached에 Key[{0}]에 해당하는 값을 저장하는데 실패했습니다.", key)); }
/// <summary> /// IDataReader 정보를 <paramref name="rowMapFunc"/>가 병렬 방식으로 처리하여 대상 객체로 빌드합니다. /// </summary> /// <typeparam name="T">대상 객체의 수형</typeparam> /// <param name="reader">DataReader</param> /// <param name="rowMapFunc">대상 객체를 빌드하는 함수</param> /// <param name="firstResult">첫번째 레코드 인덱스 (0부터 시작합니다. null이면 0으로 간주)</param> /// <param name="maxResults">매핑할 최대 레코드 수 (0이면, IDataReader의 끝까지 매핑합니다)</param> /// <returns>매핑된 대상 객체의 컬렉션</returns> public static IList <T> MapAsParallel <T>(this IDataReader reader, Func <AdoResultRow, T> rowMapFunc, int firstResult = 0, int maxResults = 0) { reader.ShouldNotBeNull("reader"); rowMapFunc.ShouldNotBeNull("rowMapFunc"); Guard.Assert(reader.IsClosed == false, "IDataReader가 이미 닫혀있습니다!!!"); if (IsDebugEnabled) { log.Debug("IDataReader를 읽어 수형[{0}]으로 매핑하여, 컬렉션으로 반환합니다...", typeof(T).Name); } var resultSet = new AdoResultSet(reader, firstResult, maxResults); if (resultSet.Count == 0) { return(new List <T>()); } return (resultSet.Values .AsParallel() .AsOrdered() .Select(rowMapFunc) .ToList()); }
/// <summary> /// <paramref name="source"/> 작업 결과가 <paramref name="predicate"/>에 만족하는 Task만 필터링합니다. /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="source"></param> /// <param name="predicate"></param> /// <returns></returns> public static Task <TSource> Where <TSource>(this Task <TSource> source, Func <TSource, bool> predicate) { source.ShouldNotBeNull("source"); predicate.ShouldNotBeNull("predicate"); // predicate를 실행하고, source의 필터링된 정보를 반환하기 위해, Continuation을 생성합니다. // predicate에서 false를 반환하면, 작업을 취소하고, 예외를 일으키는 작업을 반환합니다. var cts = new CancellationTokenSource(); return (source .ContinueWith(antecedent => { var result = antecedent.Result; // 결과가 만족할 수 없다면, 작업을 취소시킵니다. if (predicate(result) == false) { cts.CancelAndThrow(); } return result; }, cts.Token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default)); }
/// <summary> /// /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TOutput"></typeparam> /// <param name="inputs"></param> /// <param name="parallelOptions"></param> /// <param name="outputFactory"></param> /// <returns></returns> public static IList <TOutput> MapProperty <TInput, TOutput>(IList <TInput> inputs, ParallelOptions parallelOptions, Func <TOutput> outputFactory) { outputFactory.ShouldNotBeNull("outputFactory"); return(Map(inputs, parallelOptions, input => input.MapProperty(outputFactory, true))); }
/// <summary> /// Command의 Parameter 정보와 속성 정보를 매핑한다. (ParameterName = 속성명) 형식 /// </summary> /// <param name="command">instance of DbCommand to execute</param> /// <param name="mappingFunc">Mapping function. input = parameter name of command , result = property name of persistent object </param> /// <param name="propertyNamesToExclude">매핑에서 제외할 속성명</param> /// <returns>instance of <see cref="INameMap"/>, Key = parameter name of a specified command, Value = property name of persistent object</returns> public static INameMap Mapping(this DbCommand command, Func <string, string> mappingFunc, params string[] propertyNamesToExclude) { command.ShouldNotBeNull("command"); mappingFunc.ShouldNotBeNull("mappingFunc"); if (IsDebugEnabled) { log.Debug("Command 파라미터명을 속성명으로 매핑합니다..."); } var nameMap = new NameMap(); var excludeNames = (propertyNamesToExclude != null) ? propertyNamesToExclude.ToList() : new List <string>(); foreach (IDataParameter parameter in command.Parameters) { var paramName = parameter.ParameterName.RemoveParameterPrefix(); if (paramName.IsNotWhiteSpace()) { var propertyName = mappingFunc(paramName); if (propertyName.IsNotWhiteSpace() && excludeNames.Contains(propertyName, StringComparer.Ordinal) == false) { nameMap.Add(paramName, propertyName); } } } if (IsDebugEnabled) { log.Debug("Command 파라미터명-속성명 매핑 결과 = " + nameMap.CollectionToString()); } return(nameMap); }
/// <summary> /// 컬럼명=속성명 매핑함수를 이용하여 지정된 DataReader의 컬럼명을 속성명으로 매핑한다. /// </summary> /// <param name="reader">instance of IDataReader</param> /// <param name="mappingFunc">mapping function</param> /// <param name="propertyNamesToExclude">매핑에서 제외할 속성명</param> /// <returns>instance of <see cref="INameMap"/></returns> public static INameMap Mapping(this IDataReader reader, Func <string, string> mappingFunc, params string[] propertyNamesToExclude) { reader.ShouldNotBeNull("reader"); mappingFunc.ShouldNotBeNull("mappingFunc"); if (IsDebugEnabled) { log.Debug("지정된 DataReader의 컬럼명을 속성명으로 매핑합니다..."); } var nameMap = new NameMap(); var excludeNames = (propertyNamesToExclude != null) ? propertyNamesToExclude.ToList() : new List <string>(); for (int i = 0; i < reader.FieldCount; i++) { var columnName = reader.GetName(i); if (columnName.IsNotWhiteSpace()) { var propertyName = mappingFunc(columnName); if (propertyName.IsNotWhiteSpace() && excludeNames.Contains(propertyName, StringComparer.Ordinal) == false) { nameMap.Add(columnName, propertyName); } } } if (IsDebugEnabled) { log.Debug("컬럼명-속성명 매핑 결과 = " + nameMap.CollectionToString()); } return(nameMap); }
/// <summary> /// <paramref name="table"/>의 정보를 Persistent object로 병렬로 변환하여 제공합니다. /// </summary> /// <typeparam name="T">Persistent object 의 수형</typeparam> /// <param name="table"><see cref="DataTable"/></param> /// <param name="rowMapper">매핑 함수</param> /// <param name="firstResult">Persistent object를 만들 첫번째 레코드 인덱스 (0부터 시작)</param> /// <param name="maxResults">Persistent object를 만들 최대 레코드 수 (0이거나 null이면 DataReader 끝까지)</param> /// <returns>Persistent object의 컬렉션</returns> public static ParallelQuery <T> MapAsParallel <T>(this DataTable table, Func <DataRow, T> rowMapper, int firstResult = 0, int maxResults = 0) { table.ShouldNotBeNull("table"); rowMapper.ShouldNotBeNull("rowMapper"); if (IsDebugEnabled) { log.Debug("Mapping Function를 이용하여 DataTable로부터 [{0}] 수형의 객체를 병렬로 생성합니다. firstResult=[{1}], maxResults=[{2}]", typeof(T).FullName, firstResult, maxResults); } var firstCount = Math.Max(0, firstResult); var maxCount = maxResults; if (maxCount <= 0) { maxCount = table.Rows.Count; } return (table.Rows .Cast <DataRow>() .AsParallel() .AsOrdered() .Skip(firstCount) .Take(maxCount) .Select(rowMapper)); }
/// <summary> /// <paramref name="reader"/>의 레코드 정보를 <paramref name="nameMap"/>를 통해 매핑을 수행하는데, 계속조건 (<paramref name="continuationCondition"/>) 이 만족할때까지만 수행한다. /// </summary> /// <typeparam name="T">대상 객체</typeparam> /// <param name="reader">IDataReader 객체</param> /// <param name="targetFactory">대상 객체 생성용 Factory</param> /// <param name="nameMap">DB 컬럼명- 클래스 속성명 매핑 정보</param> /// <param name="continuationCondition">진행 조건 (False가 나올 때까지 진행합니다)</param> /// <param name="additionalMapping">컬럼-속성 단순 값 매핑 이외에 부가적인 매핑을 수행하기 위해 제공되는 델리게이트</param> /// <returns>매핑된 대상 객체 컬렉션</returns> public static IEnumerable <T> MapWhile <T>(this IDataReader reader, Func <T> targetFactory, INameMap nameMap, Func <IDataReader, bool> continuationCondition, Action <IDataReader, T> additionalMapping = null) { targetFactory.ShouldNotBeNull("targetFactory"); nameMap.ShouldNotBeNull("nameMap"); var columNames = nameMap.Keys.ToArray(); var targetAccessor = GetDynamicAccessor <T>(); Func <IDataReader, T> @readerMapFunc = dr => { var target = targetFactory(); columNames.RunEach(colName => targetAccessor.SetPropertyValue(target, nameMap[colName], dr.AsValue(colName))); if (additionalMapping != null) { additionalMapping(dr, target); } return(target); }; return(MapWhile(reader, readerMapFunc, continuationCondition)); }
/// <summary> /// 사용자가 제공하는 다음 조각 크기를 구하는 함수에 따라, 분할을 수행하는 분할자를 제공합니다. /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="source"></param> /// <param name="nextChunkSizeFunc"></param> /// <returns></returns> public static OrderablePartitioner <TSource> Create <TSource>(IEnumerable <TSource> source, Func <int, int> nextChunkSizeFunc) { source.ShouldNotBeNull("source"); nextChunkSizeFunc.ShouldNotBeNull("nextChunkSizeFunc"); return(new ChunkPartitioner <TSource>(source, nextChunkSizeFunc)); }
/// <summary> /// <paramref name="function"/>을 수행할 때, 예외가 발생하면 try-finally block이나 종료자를 수행하지 않고 빠져나가도록 Wrapping합니다. /// (이런 수행 방식을 Fail Fast라고 합니다.) /// </summary> /// <typeparam name="T">함수의 반환 값의 수형</typeparam> /// <param name="function">수행할 함수</param> /// <returns></returns> public static Func <T> WithFailFast <T>(this Func <T> function) { function.ShouldNotBeNull("function"); return(() => { try { return function(); } catch (Exception ex) { if (log.IsWarnEnabled) { log.Warn("지정된 함수 실행에 실패하여, FailFast로 마무리 짓습니다."); log.Warn(ex); } // 디버깅 모드라면, 디버깅 중단을 알립니다. if (Debugger.IsAttached) { Debugger.Break(); } else { // NET-3.5에서는 string 인자 하나만 받는 메소드 밖에 없다. Environment.FailFast("예기치 못한 예외가 발생했습니다. Fail fast 방식으로 빠져나갑니다." + Environment.NewLine + ex); } } throw new InvalidOperationException("여기까지 오면 잘못된 작업이 수행된 것입니다^^"); }); }
/// <summary> /// EAP (Event-based Asynchronous Pattern : 이벤트기반 비동기 패턴) 작업에서, 작업 완료시의 후속조치를 정의합니다. /// </summary> /// <typeparam name="T">비동기 작업 결과물의 수형</typeparam> /// <param name="tcs">비동기 작업을 표현하는 delegate</param> /// <param name="e">비동기 작업완료 이벤트 인자</param> /// <param name="getResult">작업완료 시에 결과 반환 메소드</param> /// <param name="unregisterHandler">작업완료 이벤트 핸들러를 등록취소하는 Action</param> public static void HandleCompletion <T>(TaskCompletionSource <T> tcs, AsyncCompletedEventArgs e, Func <T> getResult, Action unregisterHandler) { tcs.ShouldNotBeNull("tcs"); e.ShouldNotBeNull("e"); if (e.UserState != tcs) { return; } getResult.ShouldNotBeNull("getResult"); if (e.Cancelled) { tcs.TrySetCanceled(); } else if (e.Error != null) { tcs.TrySetException(e.Error); } else { tcs.TrySetResult(getResult()); } if (unregisterHandler != null) { unregisterHandler(); } }
/// <summary> /// Samples a function equidistant within the provided interval. /// </summary> /// <param name="function">The real-domain function to sample.</param> /// <param name="intervalBegin">The real domain interval begin where to start sampling.</param> /// <param name="intervalEnd">The real domain interval end where to stop sampling.</param> /// <param name="sampleCount">The number of samples to generate.</param> /// <typeparam name="T">The value type of the function to sample.</typeparam> /// <returns>The generated sample vector.</returns> public static T[] EquidistantInterval <T>(Func <double, T> function, double intervalBegin, double intervalEnd, int sampleCount) { function.ShouldNotBeNull("function"); sampleCount.ShouldBePositiveOrZero("sampleCount"); if (sampleCount == 0) { return(new T[0]); } if (sampleCount == 1) { return new T[] { function((intervalBegin + intervalEnd) / 2.0) } } ; var step = (intervalEnd - intervalBegin) / (sampleCount - 1); return (Enumerable.Range(0, sampleCount) .AsParallel() .AsOrdered() .Select(i => (i != sampleCount - 1) ? function(intervalBegin + step * i) : function(intervalEnd)) .ToArray()); }
/// <summary> /// 이분법으로 y = func(x) 함수의 [lower, upper] 구간에 대해, 근을 찾는다 (y=0 이되는 x 값) /// </summary> /// <param name="func">근을 찾을 함수</param> /// <param name="lower">근을 찾을 구간의 하한</param> /// <param name="upper">근을 찾을 구간의 상한</param> /// <param name="tryCount">시도 횟수</param> /// <param name="tolerance">근의 오차허용범위</param> /// <returns>근에 해당하는 x 값. 해를 못찾으면 <see cref="double.NaN"/>을 반환한다.</returns> public override double FindRoot(Func<double, double> func, double lower, double upper, int tryCount = MathTool.DefaultTryCount, double tolerance = MathTool.Epsilon) { func.ShouldNotBeNull("func"); tolerance = Math.Abs(tolerance); if(IsDebugEnabled) log.Debug("Bisection을 이용하여, root 값을 찾습니다... func=[{0}], lower=[{1}], upper=[{2}], tryCount=[{3}], tolerance=[{4}]", func, lower, upper, tryCount, tolerance); if(lower > upper) MathTool.Swap(ref lower, ref upper); var fa = func(lower); var fb = func(upper); if(Math.Abs(fa - RootY) < tolerance) return lower; if(Math.Abs(fb - RootY) < tolerance) return upper; Guard.Assert(Math.Abs(lower - upper) > tolerance, "상하한이 같은 값을 가지면 근을 구할 수 없습니다."); if(tryCount < DefaultTryCount) tryCount = DefaultTryCount; for(var k = 0; k < tryCount; k++) { var x = (lower + upper) / 2.0; if(Math.Abs(upper - x) < tolerance || Math.Abs(lower - x) < tolerance) return x; var y = func(x); if(IsDebugEnabled) log.Debug(@"Find root... x=[{0}], y=[{1}]", x, y); // 해를 만족하던가, upper-lower의 변화가 매우 작던가.. if(Math.Abs(y - RootY) < tolerance) { if(IsDebugEnabled) log.Debug("Iteration count=[{0}]", k); return x; } if(fa * y > 0) { lower = x; fa = y; } else { upper = x; fb = y; } } return double.NaN; }
/// <summary> /// 함수의 [a,b] 구간을 적분합니다. /// </summary> /// <param name="func">적분할 함수</param> /// <param name="a">적분 시작 위치</param> /// <param name="b">적분 끝 위치</param> /// <returns>적분 값</returns> public override double Integrate(Func <double, double> func, double a, double b) { func.ShouldNotBeNull("func"); if (IsDebugEnabled) { log.Debug(@"Simpson 적분법을 이용하여 적분을 수행합니다. func=[{0}], a=[{1}], b=[{2}]", func, a, b); } func.ShouldNotBeNull("unaryFunc"); if (a > b) { return(Integrate(func, b, a)); } _steps = GetSteps(a, b, _steps); double h = (b - a) / (2.0 * _steps); double hdiv3 = h / 3; double fo = 0; double fe = 0; double N = 2 * _steps - 3; ParallelTool.ForWithStep(1, (int)N + 1, 2, () => 0.0, (i, loopState, local) => local + func(a + h * i), local => { lock (_syncLock) fo += local; }); ParallelTool.ForWithStep(1, (int)N + 1, 2, () => 0.0, (i, loopState, local) => local + func(a + h * (i + 1)), local => { lock (_syncLock) fe += local; }); //for(int i = 1; i <= N; i += 2) //{ // fo += func(a + h * i); // 홀수항 (odd) // fe += func(a + h * (i + 1)); // 짝수항 (even) //} var result = (func(a) + func(b) + 4.0 * (fo + func(b - h)) + 2.0 * fe) * hdiv3; if (IsDebugEnabled) { log.Debug(@"적분결과=[{0}]", result); } return(result); }
/// <summary> /// <paramref name="source"/>의 항목들을 <paramref name="bucketSelector"/>를 통해 그룹핑하여 빈도수를 나타냅니다. (히스토그램 처럼) /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TBucket"></typeparam> /// <param name="source"></param> /// <param name="bucketSelector"></param> /// <returns></returns> public static IEnumerable <KeyValuePair <TBucket, int> > Frequency <T, TBucket>(this IEnumerable <T> source, Func <T, TBucket> bucketSelector) { source.ShouldNotBeNull("source"); bucketSelector.ShouldNotBeNull("bucketSelector"); return(source.GroupBy(x => bucketSelector(x)).Select(g => new KeyValuePair <TBucket, int>(g.Key, g.Count()))); }
/// <summary> /// 생성자 /// </summary> /// <param name="getter">Indexer 요소 조회 함수</param> /// <param name="setter">Indexer 요소 설정 함수</param> public NamedIndexer(Func <TIndex, TResult> getter, Action <TIndex, TResult> setter) { getter.ShouldNotBeNull("getter"); setter.ShouldNotBeNull("setter"); _getter = getter; _setter = setter; }
/// <summary> /// sequence 를 지정된 수형으로 변환한 sequence로 만듭니다. /// Nullable로 변환시에는 x=>(double?)x 와 같은 expression을 넣어줘야 제대로 됩니다. /// </summary> /// <typeparam name="TResult">변환할 수형</typeparam> /// <param name="iterator">반복자</param> /// <param name="converter">시퀀스 요소의 변환방식을 표현한 변환 메소드</param> /// <returns>변환된 시퀀스</returns> public static IEnumerable <TResult> ConvertUnsafe <TResult>(this IEnumerator iterator, Func <object, TResult> converter) { converter.ShouldNotBeNull("converter"); while (iterator.MoveNext()) { yield return(converter(iterator.Current)); } }
/// <summary> /// Initializes a new instance of the Weibull class. /// </summary> /// <param name="shape">The shape of the Weibull distribution.</param> /// <param name="scale">The scale of the Weibull distribution.</param> /// <param name="randomFactory">난수발생기 Factory</param> public Weibull(double shape, double scale, Func<Random> randomFactory = null) { randomFactory.ShouldNotBeNull("randomFactory"); if(IsDebugEnabled) log.Debug(@"Weibull 분포를 표현하는 인스턴스를 생성했습니다. shape=[{0}], scale=[{1}]", shape, scale); SetParameters(shape, scale); _random = (randomFactory != null) ? randomFactory() : MathTool.GetRandomFactory().Invoke(); }
/// <summary> /// y = func(x) 함수의 [lower, upper] 구간에 대해, 근을 찾는다 ( func(x) = 0 인 x 값 ) /// </summary> /// <param name="func">근을 찾을 함수</param> /// <param name="lower">근을 찾을 구간의 하한</param> /// <param name="upper">근을 찾을 구간의 상한</param> /// <param name="tryCount">시도 횟수</param> /// <param name="tolerance">근의 오차허용범위</param> /// <returns>근에 해당하는 x 값. 해를 못찾으면 <see cref="double.NaN"/>을 반환한다.</returns> public override double FindRoot(Func<double, double> func, double lower, double upper, int tryCount = MathTool.DefaultTryCount, double tolerance = MathTool.Epsilon) { func.ShouldNotBeNull("func"); tolerance = Math.Abs(tolerance); if(IsDebugEnabled) log.Debug(@"Find root by Secant... func=[{0}], lower=[{1}], upper=[{2}], tryCount=[{3}], tolerance=[{4}]", func, lower, upper, tryCount, tolerance); if(lower > upper) MathTool.Swap(ref lower, ref upper); if(Math.Abs(func(lower).Clamp(RootY, tolerance) - RootY) < double.Epsilon) return lower; if(Math.Abs(func(upper).Clamp(RootY, tolerance) - RootY) < double.Epsilon) return upper; if(tryCount < DefaultTryCount) tryCount = DefaultTryCount; double root, xt; var y1 = func(lower); var y2 = func(upper); if(Math.Abs(y1) < Math.Abs(y2)) { root = lower; xt = upper; MathTool.Swap(ref y1, ref y2); } else { xt = lower; root = upper; } for(var i = 0; i < tryCount; i++) { var dx = (xt - root) * y2 / (y2 - y1); xt = root; y1 = y2; root += dx; y2 = func(root); if(IsDebugEnabled) log.Debug(@"Secant root=[{0}]", root); if((Math.Abs(dx - RootY) < double.Epsilon) || (Math.Abs((y2 - y1) - RootY) < double.Epsilon)) return root; // if(Math.Abs(Math.Abs(dx).Clamp(RootY, tolerance) - RootY) < double.Epsilon || Math.Abs(Math.Abs(y2 - y1).Clamp(RootY, tolerance) - RootY) < double.Epsilon) // return root; } return double.NaN; }
/// <summary> /// y = func(x) 함수의 [lower, upper] 구간에서 f(x)의 최소 값이 되는 x를 구합니다. /// </summary> /// <param name="func">함수</param> /// <param name="lower">구간의 하한</param> /// <param name="upper">구간의 상한</param> /// <param name="tryCount">시도횟수</param> /// <param name="tolerance">허용 오차</param> /// <returns>f(x)가 최소값이 되는 x 값, 검색 실패시에는 double.NaN을 반환한다</returns> public override double FindMiminum(Func<double, double> @func, double lower, double upper, int tryCount = MathTool.DefaultTryCount, double tolerance = MathTool.Epsilon) { @func.ShouldNotBeNull("func"); tolerance = Math.Abs(tolerance); if(IsDebugEnabled) log.Debug("Find root by GoldenSectionMinimumFinder... " + "func=[{0}], lower=[{1}], upper=[{2}], tryCount=[{3}], tolerance=[{4}]", func, lower, upper, tryCount, tolerance); if(tryCount < MathTool.DefaultTryCount) tryCount = MathTool.DefaultTryCount; if(lower > upper) MathTool.Swap(ref lower, ref upper); var t = GodenRatio * (upper - lower); var c = lower + t; var d = upper - t; var fc = @func(c); var fd = @func(d); for(var i = 0; i < tryCount; i++) { if(fc > fd) { lower = c; c = d; fc = fd; d = upper - GodenRatio * (upper - lower); if(Math.Abs(d - c) <= tolerance) return c; fd = @func(d); } else { upper = d; d = c; fd = fc; c = lower + GodenRatio * (upper - lower); if(Math.Abs(d - c) <= tolerance) return d; fc = @func(c); } } return double.NaN; }
/// <summary> /// 함수의 [a,b] 구간을 적분합니다. /// </summary> /// <param name="func">적분할 함수</param> /// <param name="a">적분 시작 위치</param> /// <param name="b">적분 끝 위치</param> /// <returns>적분 값</returns> public override double Integrate(Func<double, double> func, double a, double b) { func.ShouldNotBeNull("func"); if(IsDebugEnabled) log.Debug(@"Simpson 적분법을 이용하여 적분을 수행합니다. func=[{0}], a=[{1}], b=[{2}]", func, a, b); func.ShouldNotBeNull("unaryFunc"); if(a > b) return Integrate(func, b, a); _steps = GetSteps(a, b, _steps); double h = (b - a) / (2.0 * _steps); double hdiv3 = h / 3; double fo = 0; double fe = 0; double N = 2 * _steps - 3; ParallelTool.ForWithStep(1, (int)N + 1, 2, () => 0.0, (i, loopState, local) => local + func(a + h * i), local => { lock(_syncLock) fo += local; }); ParallelTool.ForWithStep(1, (int)N + 1, 2, () => 0.0, (i, loopState, local) => local + func(a + h * (i + 1)), local => { lock(_syncLock) fe += local; }); //for(int i = 1; i <= N; i += 2) //{ // fo += func(a + h * i); // 홀수항 (odd) // fe += func(a + h * (i + 1)); // 짝수항 (even) //} var result = (func(a) + func(b) + 4.0 * (fo + func(b - h)) + 2.0 * fe) * hdiv3; if(IsDebugEnabled) log.Debug(@"적분결과=[{0}]", result); return result; }
/// <summary> /// 함수의 [a,b] 구간을 적분합니다. /// </summary> /// <param name="func">적분할 함수</param> /// <param name="a">적분 시작 위치</param> /// <param name="b">적분 끝 위치</param> /// <returns>적분 값</returns> public override double Integrate(Func<double, double> func, double a, double b) { func.ShouldNotBeNull("func"); if(IsDebugEnabled) log.Debug(@"중점접(MidValue)를 이용하여 적분을 수행합니다. func=[{0}], a=[{1}], b=[{2}]", func, a, b); func.ShouldNotBeNull("f"); if(a > b) MathTool.Swap(ref a, ref b); int n = GetSteps(a, b, Steps); double h = (b - a) / n; double hdiv2 = h / 2; double n2 = n * 2; double result = 0; ParallelTool.ForWithStep(1, (int)(n2 + 1), 2, () => 0.0, (i, loopState, local) => local + func(a + i * hdiv2), local => { lock(_syncLock) result += local; }); //for(int i = 1; i < n2; i += 2) // result += func(a + i * hdiv2); result *= h; if(IsDebugEnabled) log.Debug(@"적분 결과=[{0}]", result); return result; }
/// <summary> /// 함수의 [a,b] 구간을 적분합니다. /// </summary> /// <param name="func">적분할 함수</param> /// <param name="a">적분 시작 위치</param> /// <param name="b">적분 끝 위치</param> /// <returns>적분 값</returns> public override double Integrate(Func<double, double> func, double a, double b) { func.ShouldNotBeNull("func"); if(IsDebugEnabled) log.Debug(@"Romberg 적분법을 이용하여 적분을 수행합니다. func=[{0}], a=[{1}], b=[{2}]", func, a, b); if(a > b) MathTool.Swap(ref a, ref b); if((_rom == null) || (_rom.GetLength(1) == _order)) _rom = new double[2,_order]; double h = (b - a); _rom[0, 0] = 0.5d * h * (func(a) + func(b)); for(int i = 2, ipower = 1; i <= _order; i++, ipower *= 2, h /= 2) { // approximation using the trapezoid rule. double sum = 0; for(var j = 1; j <= ipower; j++) sum += func(a + h * (j - 0.5)); // Richardson extrapolation _rom[1, 0] = 0.5 * (_rom[0, 0] + (h * sum)); for(int k = 1, kpower = 4; k < i; k++, kpower *= 4) _rom[1, k] = (kpower * _rom[1, k - 1] - _rom[0, k - 1]) / (kpower - 1); // save the extrapolated value for the next integration for(int j = 0; j < i; j++) _rom[0, j] = _rom[1, j]; } if(IsDebugEnabled) log.Debug(@"적분결과=[{0}]", _rom[0, _order - 1]); return _rom[0, _order - 1]; }
// Methods public GoldenSection(Func<double, double> func, double a, double b, int n) { func.ShouldNotBeNull("func"); int num = 0; double num2 = 0.0; double num3 = 0.0; double x = 0.0; double num5 = 0.0; double num6 = 0.0; double num7 = 0.0; num2 = (3.0 - Math.Sqrt(5.0)) / 2.0; num3 = (Math.Sqrt(5.0) - 1.0) / 2.0; x = a + (num2 * (b - a)); num5 = a + (num3 * (b - a)); num6 = func(x); num7 = func(num5); for(num = 1; num <= n; num++) { if(num6 <= num7) { b = num5; num5 = x; num7 = num6; x = a + (num2 * (b - a)); num6 = func(x); } else { a = x; x = num5; num6 = num7; num5 = a + (num3 * (b - a)); num7 = func(num5); } } resultA = a; resultB = b; }
/// <summary> /// 원본 속성명-속성값 정보를 대상 인스턴스의 속성명에 값을 설정한다. /// </summary> /// <param name="source">원본 정보 (Name-Value)</param> /// <param name="targetFactory">복사 대상 인스턴스 생성 델리게이트</param> /// <param name="mapOptions">매핑 옵션</param> /// <param name="propertyNamesToExclude">복사 제외 속성 명</param> public static object Map(IDictionary source, Func<object> targetFactory, MapPropertyOptions mapOptions, params string[] propertyNamesToExclude) { targetFactory.ShouldNotBeNull("targetFactory"); var target = targetFactory(); if(IsDebugEnabled) log.Debug("원본의 속성-값을 대상 인스턴스의 속성 값으로 복사합니다... " + @"source=[{0}], target=[{1}], mapOptions=[{2}], propertyNamesToExclude=[{3}]", source, target, mapOptions, propertyNamesToExclude.CollectionToString()); var excludes = new List<string>(propertyNamesToExclude); var accessor = DynamicAccessorFactory.CreateDynamicAccessor(target.GetType(), mapOptions.SuppressException); var targetPropertyNames = accessor.GetPropertyNames().Except(excludes).ToList(); foreach(string name in source.Keys) { var sourceName = name; if(excludes.Any(epn => StringTool.EqualTo(epn, sourceName))) continue; var canSetPropertyValue = targetPropertyNames.Any(tpn => StringTool.EqualTo(tpn, sourceName)); if(canSetPropertyValue) { if(mapOptions.IgnoreCase) { var targetPropertyName = targetPropertyNames.FirstOrDefault(tpn => StringTool.EqualTo(tpn, sourceName)); if(targetPropertyName.IsNotWhiteSpace()) accessor.SetPropertyValue(target, targetPropertyName, source[sourceName]); } else { accessor.SetPropertyValue(target, sourceName, source[sourceName]); } } } return target; }
public Rayleigh(double scale, Func<Random> randomFactory) { SetParameters(scale); randomFactory.ShouldNotBeNull("randomFactory"); _random = randomFactory(); }
public Pareto(double scale, double shape, Func<Random> randomFactory = null) { SetParameters(scale, shape); randomFactory.ShouldNotBeNull("randomFactory"); _random = randomFactory(); }
public CompressAdapter(Func<ICompressor> @compressorFactory) { @compressorFactory.ShouldNotBeNull("compressorFactory"); @_compressorFactory = @compressorFactory; }
/// <summary> /// 생성자 /// </summary> /// <param name="repositoryFactory"></param> protected AbstractSessionStateStoreProvider(Func<ICacheRepository> repositoryFactory) { repositoryFactory.ShouldNotBeNull("repositoryFactory"); CacheRepository = repositoryFactory.Invoke(); }
/// <summary> /// Command의 Parameter 정보와 속성 정보를 매핑한다. (ParameterName = 속성명) 형식 /// </summary> /// <param name="command">instance of DbCommand to execute</param> /// <param name="mappingFunc">Mapping function. input = parameter name of command , result = property name of persistent object </param> /// <param name="propertyNamesToExclude">매핑에서 제외할 속성명</param> /// <returns>instance of <see cref="INameMap"/>, Key = parameter name of a specified command, Value = property name of persistent object</returns> public static INameMap Mapping(this DbCommand command, Func<string, string> mappingFunc, params string[] propertyNamesToExclude) { command.ShouldNotBeNull("command"); mappingFunc.ShouldNotBeNull("mappingFunc"); if(IsDebugEnabled) log.Debug("Command 파라미터명을 속성명으로 매핑합니다..."); var nameMap = new NameMap(); var excludeNames = (propertyNamesToExclude != null) ? propertyNamesToExclude.ToList() : new List<string>(); foreach(IDataParameter parameter in command.Parameters) { var paramName = parameter.ParameterName.RemoveParameterPrefix(); if(paramName.IsNotWhiteSpace()) { var propertyName = mappingFunc(paramName); if(propertyName.IsNotWhiteSpace() && excludeNames.Contains(propertyName, StringComparer.Ordinal) == false) nameMap.Add(paramName, propertyName); } } if(IsDebugEnabled) log.Debug("Command 파라미터명-속성명 매핑 결과 = " + nameMap.CollectionToString()); return nameMap; }
protected AbstractOutputCacheProvider(Func<ICacheRepository> cacheRepositoryFactory) { cacheRepositoryFactory.ShouldNotBeNull("cacheRepositoryFactory"); CacheRepository = cacheRepositoryFactory(); }
/// <summary> /// 지정한 작업 생성 함수로 생성되는 작업을 순차 수행을 위한 작업 큐에 넣습니다. /// </summary> /// <param name="taskFactory"></param> public void Enqueue(Func<Task> taskFactory) { taskFactory.ShouldNotBeNull("taskFactory"); EnqueueInternal(taskFactory); }