///
/// This file is part of ILNumerics Community Edition.
///
/// ILNumerics Community Edition - high performance computing for applications.
/// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
///
/// ILNumerics Community Edition is free software: you can redistribute it and/or modify
/// it under the terms of the GNU General Public License version 3 as published by
/// the Free Software Foundation.
///
/// ILNumerics Community Edition is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with ILNumerics Community Edition. See the file License.txt in the root
/// of your distribution package. If not, see .
///
/// In addition this software uses the following components and/or licenses:
///
/// =================================================================================
/// The Open Toolkit Library License
///
/// Copyright (c) 2006 - 2009 the Open Toolkit library.
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights to
/// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
/// the Software, and to permit persons to whom the Software is furnished to do
/// so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// =================================================================================
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ILNumerics {
///
/// An artificial scope class, used by the ILNumerics memory management
///
public class ILScope : IDisposable {
internal class ILThreadingContext {
public Stack Arrays = new Stack(100);
public Stack Scopes = new Stack(100);
public void RegisterArray(ILBaseArray A) {
if (Scopes.Count > 0) /* && A.EnterScope() ) */ { //ho: commented out, because otherwise common local arrays do return false and hence get not registered in implicit conversions here!
Arrays.Push(A);
Scopes.Peek().Count++;
}
}
}
[ThreadStatic]
private static ILThreadingContext s_threadContext;
///
/// Begins an artificial scope block within a local function block
///
/// Any input arry, given as parameter for the current function
/// A new scope
/// The ILScope class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics,
/// ILScope is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once
/// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these
/// simple rules, ILNumerics is able to optimize the execution of the algorithm regarding
/// execution speed and memory footprint.
/// The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of
/// artificial scopes.
/// FreqPeaks(ILInArray inData, ILOutArray freq = null, double sampFreq = 44.1) {
///
/// using (ILScope.Enter(inData)) {
///
/// ILArray Data = check(inData);
/// ILArray retLength = min(ceil(Data.Length / 2.0 + 1), 5.0);
/// ILArray Window = stdWindowFunc(Data.Length);
/// ILArray magnitudes = abs(fft(Data * Window));
/// magnitudes = magnitudes[r(0,end / 2 + 1)];
///
/// ILArray indices = empty();
/// ILArray sorted = sort(magnitudes, indices, descending:true);
/// if (!isnull(freq))
/// freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)];
/// return magnitudes[r(0,retLength-1)];
/// }
///}]]>
///
public static IDisposable Enter(params ILBaseArray[] inputArrays) {
return new ILScope(inputArrays);
}
///
/// Begins an artificial scope block within a local function block
///
/// Any input arry, given as parameter for the current function
/// A new scope
/// The ILScope class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics,
/// ILScope is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once
/// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these
/// simple rules, ILNumerics is able to optimize the execution of the algorithm regarding
/// execution speed and memory footprint.
/// The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of
/// artificial scopes.
/// FreqPeaks(ILInArray inData, ILOutArray freq = null, double sampFreq = 44.1) {
///
/// using (ILScope.Enter(inData)) {
///
/// ILArray Data = check(inData);
/// ILArray retLength = min(ceil(Data.Length / 2.0 + 1), 5.0);
/// ILArray Window = stdWindowFunc(Data.Length);
/// ILArray magnitudes = abs(fft(Data * Window));
/// magnitudes = magnitudes[r(0,end / 2 + 1)];
///
/// ILArray indices = empty();
/// ILArray sorted = sort(magnitudes, indices, descending:true);
/// if (!isnull(freq))
/// freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)];
/// return magnitudes[r(0,retLength-1)];
/// }
///}]]>
///
public static IDisposable Enter(ILBaseArray inputArrays) {
return new ILScope(inputArrays);
}
///
/// The threading context - individual for each thread
///
internal static ILThreadingContext Context {
get {
ILThreadingContext ret = s_threadContext;
if (ret == null) {
s_threadContext = new ILThreadingContext();
ret = s_threadContext;
}
return ret;
}
}
internal int Count = 0;
internal ILScope(ILBaseArray array) {
if (!object.Equals(array,null)) {
Stack stack = Context.Arrays;
int oldStackCount = stack.Count;
if (array.EnterScope()) {
stack.Push(array);
}
Count = stack.Count - oldStackCount;
}
Context.Scopes.Push(this);
}
internal ILScope(params ILBaseArray[] inputArrays) {
if (inputArrays != null) {
Stack stack = Context.Arrays;
int oldStackCount = stack.Count;
foreach (var a in inputArrays) {
if (!object.Equals(a, null)) {
if (a.EnterScope()) {
stack.Push(a);
}
}
}
Count = stack.Count - oldStackCount;
}
Context.Scopes.Push(this);
}
#region IDisposable Members
///
/// Dispose all arrays in this scope
///
public void Dispose() {
Stack stack = Context.Arrays;
for (int i = Count; i-- > 0; ) {
stack.Pop().LeaveScope();
}
#if VERBOSE
System.Diagnostics.Debug.Assert(object.Equals(Context.Scopes.Peek(), this));
System.Diagnostics.Debug.WriteLine ("Leaving scope {0} - disposing {1} arrays",Context.Scopes.Peek().GetHashCode(),Count);
#endif
Context.Scopes.Pop();
}
#endregion
}
}