/// <summary> /// Performs a binary function on lhs and rhs on a specific property (axis). /// </summary> /// <param name="rhs"></param> /// <param name="property">Which property from <see cref="DoubleArray.Properties"/> dimension to select and apply <paramref name="function"/> on.</param> /// <param name="function">The function to call for every value in this array.</param> /// <returns></returns> public virtual DoubleArray Function(DoubleArray rhs, int property, BinaryFunctionHandler function) { var lhs = this; if (lhs.IsScalar && lhs.Properties > property && rhs.IsScalar && rhs.Properties > property) { return(lhs[property] * rhs[property]); } int offset = property; DoubleArray ret; int len; if (lhs.IsScalar && lhs.Properties > property) { ret = rhs.Clone(); len = ret.Count; var propsRhs = rhs.Properties; var lhs_val = lhs[property]; fixed(double *rhs_ptr = rhs, ret_ptr = ret) for (int i = 0; i < len; i++, offset += propsRhs) { ret_ptr[offset] = function(lhs_val, rhs_ptr[offset]); } return(ret); } else if (rhs.IsScalar && rhs.Properties > property) { ret = lhs.Clone(); len = ret.Count; var propsLhs = lhs.Properties; var rhsVal = rhs[property]; fixed(double *lhs_ptr = lhs, ret_ptr = ret) for (int i = 0; i < len; i++, offset += propsLhs) { ret_ptr[offset] = function(lhs_ptr[offset], rhsVal); } return(ret); } else { ret = lhs.Clone(); len = ret.Count; var propsLhs = lhs.Properties; var propsRhs = rhs.Properties; var rhsOffset = property; fixed(double *lhs_ptr = rhs, rhs_ptr = rhs, ret_ptr = ret) for (int i = 0; i < len; i++, offset += propsLhs, rhsOffset += propsRhs) { ret_ptr[offset] = function(lhs_ptr[offset], rhs_ptr[rhsOffset]); } return(ret); } }
/// <summary> /// Performs a binary function on lhs and rhs. /// </summary> /// <param name="rhs">The rhs of the equation, 'this' is lhs.</param> /// <param name="function">The function to call for every value in this array.</param> /// <returns></returns> public virtual DoubleArray Function(DoubleArray rhs, BinaryFunctionHandler function) { var lhs = this; if (lhs.IsScalar && lhs.Properties == 1 && rhs.IsScalar && lhs.Properties == 1) { return(function(lhs.Value, rhs.Value)); } DoubleArray ret; int len; if (lhs.IsScalar && lhs.Properties == 1) { ret = rhs.Clone(); len = ret.LinearLength; var lhs_val = lhs.Value; fixed(double *rhs_ptr = rhs, ret_ptr = ret) for (int i = 0; i < len; i++) { ret_ptr[i] = function(lhs_val, rhs_ptr[i]); } return(ret); } else if (rhs.IsScalar && rhs.Properties == 1) { ret = lhs.Clone(); len = ret.LinearLength; var rhsVal = rhs.Value; fixed(double *lhs_ptr = lhs, ret_ptr = ret) for (int i = 0; i < len; i++) { ret_ptr[i] = function(lhs_ptr[i], rhsVal); } return(ret); } else { var propsLhs = lhs.LinearLength; var propsRhs = rhs.LinearLength; ret = propsLhs >= propsRhs?lhs.Clone() : rhs.Clone(); len = ret.LinearLength; if (propsRhs % propsLhs != 0) throw new ReshapeException($"Unable to broadcast lhs against rhs, ({propsLhs}, {propsRhs})."); fixed(double *lhs_ptr = rhs, rhs_ptr = rhs, ret_ptr = ret) if (propsRhs != propsLhs) { for (int i = 0; i < len; i++) { ret_ptr[i] = function(lhs_ptr[i % propsLhs], rhs_ptr[i % propsRhs]); } } else { for (int i = 0; i < len; i++) { ret_ptr[i] = function(lhs_ptr[i], rhs_ptr[i]); } } return(ret); } }