Hi Nicholas,
I tried your custom interface solution. I end up with only 4 compile
erros, in two lines. Search for token "errors" in the source code
shown below. In line
private static readonly Ts_SimpleMathImplementation= new
Ts_SimpleMath();
it is like it doesn't know how to create a new instance of
Ts_SimpleMath. The "new ()" in line
where Ti_SimpleMath : I_SimpleMath<Ti>, new()
presumably means that Ti_SimpleMath must have a public parameterless
constructor. How can I specify the constructor of Ti_SimpleMath ? In
I_SimpleMath<T>? How?
I know that I ended up not using "Ti_SimpleMathImplementation", but I
would keep it just in case. I do use "Ts_SimpleMathImplementation".
Sorry about the long post.
If you know why I'm getting those errors, please let me know.
Thank you.
PS: I'm starting to think about not using generics for this purpose,
and instead define two or three classes like "C_Filter_MA_u08_u32",
"C_Filter_MA_u16_u32" and "C_Filter_MA_double_double", for instance,
because I'll probably end up with fewer lines of code. All this has
really surprised me.
---------------------------------------
using System;
using System.Collections.Generic;
// These "using" are the C# equivalent ones to "typedef" in C++.
using u08 =System.Byte;
using u16 =System.UInt16;
using u32 =System.UInt32;
using u64 =System.UInt64;
using i08 =System.SByte;
using i16 =System.Int16;
using i32 =System.Int32;
using i64 =System.Int64;
namespace N_Filters
{
#region Interfaces and their implementations.
// ===============================================================
// Interfaces cannot contain operators.
public interface I_SimpleMath<T>
{
T Add(T val1, T val2);
T Subtract(T val1, T val2);
T Multiply(T val1, T val2);
T Divide(T val1, T val2);
T ShiftLeft(T val1,u08 shift_amount);
T ShiftRight(T val1,u08 shift_amount);
} // I_SimpleMath
// ===============================================================
public class C_SimpleMath_u08 : I_SimpleMath<u08>
{
public u08 Add(u08 val1, u08 val2)
{
return((u08)(val1+val2));
}
public u08 Subtract(u08 val1, u08 val2)
{
return((u08)(val1-val2));
}
public u08 Multiply(u08 val1, u08 val2)
{
return((u08)(val1*val2));
}
public u08 Divide(u08 val1, u08 val2)
{
return((u08)(val1/val2));
}
public u08 ShiftLeft(u08 val1,u08 shift_amount)
{
return((u08)(val1<<shift_amount));
}
public u08 ShiftRight(u08 val1,u08 shift_amount)
{
return((u08)(val1>>shift_amount));
}
} // C_SimpleMath_u08
// ===============================================================
public class C_SimpleMath_u16 : I_SimpleMath<u16>
{
public u16 Add(u16 val1, u16 val2)
{
return((u16)(val1+val2));
}
public u16 Subtract(u16 val1, u16 val2)
{
return((u16)(val1-val2));
}
public u16 Multiply(u16 val1, u16 val2)
{
return((u16)(val1*val2));
}
public u16 Divide(u16 val1, u16 val2)
{
return((u16)(val1/val2));
}
public u16 ShiftLeft(u16 val1,u08 shift_amount)
{
return((u16)(val1<<shift_amount));
}
public u16 ShiftRight(u16 val1,u08 shift_amount)
{
return((u16)(val1>>shift_amount));
}
} // C_SimpleMath_u16
// ===============================================================
public class C_SimpleMath_u32 : I_SimpleMath<u32>
{
public u32 Add(u32 val1, u32 val2)
{
return((u32)(val1+val2));
}
public u32 Subtract(u32 val1, u32 val2)
{
return((u32)(val1-val2));
}
public u32 Multiply(u32 val1, u32 val2)
{
return((u32)(val1*val2));
}
public u32 Divide(u32 val1, u32 val2)
{
return((u32)(val1/val2));
}
public u32 ShiftLeft(u32 val1,u08 shift_amount)
{
return((u32)(val1<<shift_amount));
}
public u32 ShiftRight(u32 val1,u08 shift_amount)
{
return((u32)(val1>>shift_amount));
}
} // C_SimpleMath_u32
// ===============================================================
public class C_SimpleMath_u64 : I_SimpleMath<u64>
{
public u64 Add(u64 val1, u64 val2)
{
return((u64)(val1+val2));
}
public u64 Subtract(u64 val1, u64 val2)
{
return((u64)(val1-val2));
}
public u64 Multiply(u64 val1, u64 val2)
{
return((u64)(val1*val2));
}
public u64 Divide(u64 val1, u64 val2)
{
return((u64)(val1/val2));
}
public u64 ShiftLeft(u64 val1,u08 shift_amount)
{
return((u64)(val1<<shift_amount));
}
public u64 ShiftRight(u64 val1,u08 shift_amount)
{
return((u64)(val1>>shift_amount));
}
} // C_SimpleMath_u64
// ===============================================================
public class C_SimpleMath_i08 : I_SimpleMath<i08>
{
public i08 Add(i08 val1, i08 val2)
{
return((i08)(val1+val2));
}
public i08 Subtract(i08 val1, i08 val2)
{
return((i08)(val1-val2));
}
public i08 Multiply(i08 val1, i08 val2)
{
return((i08)(val1*val2));
}
public i08 Divide(i08 val1, i08 val2)
{
return((i08)(val1/val2));
}
public i08 ShiftLeft(i08 val1,u08 shift_amount)
{
return((i08)(val1<<shift_amount));
}
public i08 ShiftRight(i08 val1,u08 shift_amount)
{
return((i08)(val1>>shift_amount));
}
} // C_SimpleMath_i08
// ===============================================================
public class C_SimpleMath_i16 : I_SimpleMath<i16>
{
public i16 Add(i16 val1, i16 val2)
{
return((i16)(val1+val2));
}
public i16 Subtract(i16 val1, i16 val2)
{
return((i16)(val1-val2));
}
public i16 Multiply(i16 val1, i16 val2)
{
return((i16)(val1*val2));
}
public i16 Divide(i16 val1, i16 val2)
{
return((i16)(val1/val2));
}
public i16 ShiftLeft(i16 val1,u08 shift_amount)
{
return((i16)(val1<<shift_amount));
}
public i16 ShiftRight(i16 val1,u08 shift_amount)
{
return((i16)(val1>>shift_amount));
}
} // C_SimpleMath_i16
// ===============================================================
public class C_SimpleMath_i32 : I_SimpleMath<i32>
{
public i32 Add(i32 val1, i32 val2)
{
return((i32)(val1+val2));
}
public i32 Subtract(i32 val1, i32 val2)
{
return((i32)(val1-val2));
}
public i32 Multiply(i32 val1, i32 val2)
{
return((i32)(val1*val2));
}
public i32 Divide(i32 val1, i32 val2)
{
return((i32)(val1/val2));
}
public i32 ShiftLeft(i32 val1,u08 shift_amount)
{
return((i32)(val1<<shift_amount));
}
public i32 ShiftRight(i32 val1,u08 shift_amount)
{
return((i32)(val1>>shift_amount));
}
} // C_SimpleMath_i32
// ===============================================================
public class C_SimpleMath_i64 : I_SimpleMath<i64>
{
public i64 Add(i64 val1, i64 val2)
{
return((i64)(val1+val2));
}
public i64 Subtract(i64 val1, i64 val2)
{
return((i64)(val1-val2));
}
public i64 Multiply(i64 val1, i64 val2)
{
return((i64)(val1*val2));
}
public i64 Divide(i64 val1, i64 val2)
{
return((i64)(val1/val2));
}
public i64 ShiftLeft(i64 val1,u08 shift_amount)
{
return((i64)(val1<<shift_amount));
}
public i64 ShiftRight(i64 val1,u08 shift_amount)
{
return((i64)(val1>>shift_amount));
}
} // C_SimpleMath_i64
// ===============================================================
public class C_SimpleMath_double : I_SimpleMath<double>
{
public double Add(double val1, double val2)
{
return((double)(val1+val2));
}
public double Subtract(double val1, double val2)
{
return((double)(val1-val2));
}
public double Multiply(double val1, double val2)
{
return((double)(val1*val2));
}
public double Divide(double val1, double val2)
{
return((double)(val1/val2));
}
public double ShiftLeft(double val1,u08 shift_amount)
{
return(val1*Math.Pow(2.0,(double)shift_amount));
}
public double ShiftRight(double val1,u08 shift_amount)
{
return(val1*Math.Pow(2.0,(double)shift_amount*-1.0));
}
} // C_SimpleMath_double
#endregion
// ===============================================================
// Moving average filter.
// Ti = T_item {u08,u16,u32,u64,i08,i16,i32,i64,double}.
// Ts = T_sum {u08,u16,u32,u64,i08,i16,i32,i64,double}.
public class C_Filter_MA<Ti,Ti_SimpleMath,Ts,Ts_SimpleMath>
where Ti : IComparable, IFormattable, IConvertible,
IComparable<Ti>, IEquatable<Ti>
where Ti_SimpleMath : I_SimpleMath<Ti>, new()
where Ts : IComparable, IFormattable, IConvertible,
IComparable<Ts>, IEquatable<Ts>
where Ts_SimpleMath : I_SimpleMath<Ts>, new()
{
// .............................................................
private static readonly Ti_SimpleMathImplementation= new
Ti_SimpleMath(); // <-- Compile errors "Invalid token '=' in class,
struct, or interface member declaration" and "Class, struct, or
interface method must have a return type".
private static readonly Ts_SimpleMathImplementation= new
Ts_SimpleMath(); // <-- Compile errors "Invalid token '=' in class,
struct, or interface member declaration" and "Class, struct, or
interface method must have a return type".
// .............................................................
protected Queue<Ti> Ti_queue; // Queue (FIFO) that
stores the items.
public int Ti_queue_capacity; // Queue does not
have any member field called Capacity.
protected Ts Ts_sum; // Sum of the values
stored in the queue.
protected u08 u08_log2ofsize; // Log2(<size of
fifo>). So, size of fifo will always be a power of 2.
// .............................................................
public C_Filter_MA(u08 u08_log2ofsize)
{
this.u08_log2ofsize=u08_log2ofsize;
Ti_queue_capacity=1<<u08_log2ofsize;
Ti_queue=new Queue<Ti>(Ti_queue_capacity);
Clear();
} // C_Filter_MA
// .............................................................
public void Clear()
{
Ti_queue.Clear();
Ts_sum=default(Ts);
} // Clear
// .............................................................
public void Init(Ti Ti_initial)
{
Ti_queue.Clear();
Ts_sum=(Ts)Convert.ChangeType(Ti_initial.ToInt32()*Ti_queue_capacity,typeof(Ts));
if (Ti_initial.Equals(default(Ti))) return;
for (int i=0;i<Ti_queue_capacity;i++)
{
Ti_queue.Enqueue(Ti_initial);
} // for
} // Init
// .............................................................
public Ti InOutData(Ti Ti_in)
{
if (Ti_queue.Count>=Ti_queue_capacity)
{
Ts_sum=Ts_SimpleMathImplementation.Subtract(Ts_sum,(Ts)Convert.ChangeType(Ti_queue.Dequeue(),typeof(Ts)));
} // if
Ti_queue.Enqueue(Ti_in);
Ts_sum=Ts_SimpleMathImplementation.Add(Ts_sum,(Ts)Convert.ChangeType(Ti_in,typeof(Ts)));
return(
(Ti)Convert.ChangeType(Ts_SimpleMathImplementation.ShiftRight(Ts_sum,u08_log2ofsize),typeof(Ti))
);
} // InOutData
// .............................................................
} // C_Filter_MA
// ===============================================================
} // N_Filters