doc_and_tools/tools/sdk/include/coding/math_util.h

263 lines
27 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.


// math.h: for math algorithm
//
// Author: Gongbing
//
// Date: 2019-11-03
#pragma once
#include "../ref/ref.h"
namespace math_util
{
enum angle_unit
{
ANGLE_UNIT_DEGREE = 0,
ANGLE_UNIT_RADIUS,
ANGLE_UNIT_GRAD,
};
// function: patition a positive integer into it's addend queue. e.g. partition 6 into 6, 5 + 1, 4 + 2, 4 + 1 + 1 ...
// num: the number should be partitioned
// result: data - (DWORD*)
// len - dims of data
// total - unused
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
// param: parameter 'param' of callback result
// from: the first starting number, the partition queue is restrict order and the first number is the beggest
// ascend: the first number's sort, when true, starting from 'from' to num; false starting from 'from' to 1
PORT_API(int) integer_partition(DWORD num, inter_module_data::set_data result, void* param, DWORD from = 1, bool ascend = true);
PORT_API(UINT64) factorial(unsigned val);
PORT_API(unsigned) greatest_common_factor(unsigned val0, unsigned val1);
PORT_API(UINT64) least_common_denominator(unsigned val0, unsigned val1);
// function: permutation a serial. e.g. permutation(3) would output: 1,2,3; 1,3,2; 2,3,1; 2,1,3; 3,1,2; 3,2,1
// elements: number of elements
// result: data - (DWORD*), an index base from ZERO array
// len - dims of data
// total - unused
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
// param: parameter 'param' of callback result
PORT_API(void) permutation(DWORD elements, inter_module_data::set_data result, void* param);
PORT_API(int) combination(DWORD elements, DWORD sub, inter_module_data::set_data result, void* param);
__declspec(novtable) struct IExpression : public ref_util::IRef
{
COM_API_DECLARE(double, result(bool* ok));
COM_API_DECLARE(bool, to_formula(inter_module_data::set_data cb, void* param));
COM_API_DECLARE(bool, to_tree_style_text(inter_module_data::set_data cb, void* param));
};
__declspec(novtable) struct IMatrix : public ref_util::IRef
{
//COM_API_DECLARE(bool, load(const wchar_t* path_file));
COM_API_DECLARE(bool, load(const char* data, const char* split = " \t")); // load from a text buffer, row end with "\r\n"
COM_API_DECLARE(bool, load(const double* data, int row, int col)); // load from a data buffer.
COM_API_DECLARE(bool, insert(const double* data, int rows, int row_pos = -1)); // load from a data buffer.
COM_API_DECLARE(double*, operator[](int row));
COM_API_DECLARE(int, row(void));
COM_API_DECLARE(int, col(void));
//COM_API_DECLARE(bool, save(const wchar_t* path_file));
// function: to set or cancel printing the result for every step
// cb: the return value of 'cb' is ignored
// data - step info text
// len - bytes of data
// total - ununsed now
// falg - always be inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
COM_API_DECLARE(bool, set_step_info_callback(inter_module_data::set_data cb, void* param));
COM_API_DECLARE(bool, row_exchange(int row1, int row2));
COM_API_DECLARE(bool, row_add(int dst_row, int src_row, double factor = 1.0f)); // perform dst_row += src_row * factor
COM_API_DECLARE(bool, row_sub(int dst_row, int src_row, double factor = 1.0f)); // perform dst_row -= src_row * factor
COM_API_DECLARE(bool, row_multiply(int dst_row, double factor)); // perform dst_row *= factor
COM_API_DECLARE(bool, row_divide(int dst_row, double factor)); // perform dst_row /= factor
COM_API_DECLARE(bool, multiply(IMatrix* r)); // perform matrix multiply
COM_API_DECLARE(bool, to_unit(void)); // make left-upper sub matrix as unit matrix
COM_API_DECLARE(bool, to_inverse(void)); // to inverse matrix
COM_API_DECLARE(bool, transpose(void)); // transpose
// function: format matrix as text for printing
// set_str: data - the text string
// len - length of the data
// total - unused
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
COM_API_DECLARE(void, to_string(inter_module_data::set_data set_str, void* param));
};
// function: get supported operators
// set_op: data - supported operator
// len - bytes of data
// total - count
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
// param: the parameter for callback 'set_op'
PORT_API(void) get_supported_operators(inter_module_data::set_data set_op, void* param);
PORT_API(void) set_valid_number_range(bool set_range, double lower = .0f, double upper = .0f);
PORT_API(bool) is_valid_number(double val);
PORT_API(angle_unit) set_angle_unit(angle_unit au = ANGLE_UNIT_DEGREE); // return previous unit
// function: to parse a maths formula into calculating binary-tree
// exp: the formula, supported operators:
// +, -
// *, /
// log, ln, cos, sin, tan, cot, asin, acos, atan, sinh, cosh (all units of trig functions are in degree, not radius !!!)
// ^, !
// support constans:
// e, pi. NOT support write-down 100 as 1e2
// support priority operators:
// (, )
// x is used as variable, must be with subscript. e.g. x0, x1, ...
//
// get_data: used in calculating to input the variable value, the return value is omitted
// data - (double*), to receive the variable value
// len - subscript of the variable
// total - unused
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
// param: the parameter for callback 'get_data'
PORT_API(IExpression*) parse_expression(const char* exp, inter_module_data::set_data get_data, void* param);
// function: to calculate an expression such as "x0^2 + cosx1 + lnx2 - x3 ..."
// exp: the formula
//
// get_data: to input the variable value, return inter_module_data::SET_RESULT_STOP to stop calculating
// data - (double*), to receive the variable value
// len - subscript of the variable
// total - unused
// flag - inter_module_data::DATA_FLAG_FINAL
// param - the same as the parameter 'param'
// param: the parameter for callback 'get_data'
PORT_API(bool) calculate_expression(const char* exp, inter_module_data::set_data get_data, void* param);
PORT_API(IMatrix*) create_matrix(int row = 0, int col = 0);
// function: to resolve a linear equation formed as "a0f(x) + a1f(x) = 0", the coefficient is used 'a' - y = ∑af(x)
// exp: linear equation
// get_data: data - (double*), to receive the variable value when flag is inter_module_data::DATA_FLAG_INSTAR
// (const double*), the coefficient array, length is in parameter 'len' when flag is inter_module_data::DATA_FLAG_FINAL
// len - subscript of the variable if flag was inter_module_data::DATA_FLAG_INSTAR;
// the result dims of (const double*)data when flag is inter_module_data::DATA_FLAG_FINAL
// total - low DWORD is the line index of source data, high DWORD is the index of the equation-group if flag was inter_module_data::DATA_FLAG_INSTAR,
// unused when inter_module_data::DATA_FLAG_FINAL
// flag - inter_module_data::DATA_FLAG_INSTAR to get variable value, inter_module_data::DATA_FLAG_FINAL to set the result
// param - the same as the parameter 'param'
// param: the parameter for callback 'get_data'
// NOTE: variables maximum number is 99 !!!
PORT_API(bool) resolve_linear_equation(const char* exp, inter_module_data::set_data get_data, void* param);
// function: generate expressions such as "a0x0 + a1x1"
// operators: double '\0' ended operator strings, such as "+\0sin\0log\0\0"
// vars: variable number, all vars variables would be placed in the expression. e.g. 3 - "a0x0 + a1x1 + a2x2"
// set_exp: callback to set the expression. when flag is inter_module_data::DATA_FLAG_ERROR then the data is the not supported operators
// total - the number of coefficient
// param: 'param' for set_exp
//
// return: false for invalid parameters, otherwise always be true
PORT_API(bool) generate_expression(const char* operators, int vars, inter_module_data::set_data set_exp, void* param);
typedef struct _fraction
{
int numerator;
unsigned denominator; // set to -1 is error
struct _fraction(int num = 0, int deno = 1);
struct _fraction(double f); // maybe failure
struct _fraction(const struct _fraction& r);
struct _fraction& operator=(const _fraction& r);
struct _fraction& operator+=(const _fraction& r);
struct _fraction& operator-=(const _fraction& r);
struct _fraction& operator*=(const _fraction& r);
struct _fraction& operator/=(const _fraction& r);
friend _fraction operator+(const _fraction& l, const _fraction& r);
friend _fraction operator-(const _fraction& l, const _fraction& r);
friend _fraction operator*(const _fraction& l, const _fraction& r);
friend _fraction operator/(const _fraction& l, const _fraction& r);
bool operator==(const _fraction& r);
bool operator!=(const _fraction& r);
bool operator>(const _fraction& r);
bool operator<(const _fraction& r);
void reduce(void);
}FRACTION, *LPFRACTION;
typedef struct _point
{
double x;
double y;
}POINT, *LPPOINT;
PORT_API(FRACTION) convert_to_fraction(double val, double* err = NULL/*to receive the error*/, int max_denominator = 0x7ffff);
PORT_API(void) rid_rear_zero(char* float_str);
PORT_API(void) rid_rear_zero(wchar_t* float_str);
PORT_API(char*) format_double_value(double val, char* buf, size_t buf_size, int digits = 6);
PORT_API(bool) replace_coefficient(const char* exp, double* coefs, int coef_num, int digits, inter_module_data::set_data result, void* param);
PORT_API(bool) is_triangle_sides(double s1, double s2, double s3);
PORT_API(double) triangle_area(double s1, double s2, double s3); // less than zero(usually -1.0f) is error
PORT_API(double) distance_of_points(const LPPOINT pt1, const LPPOINT pt2);
__declspec(novtable) struct ILine : public ref_util::IRef // we recognize 'Ax + By + C = 0' as the regular formula
{
COM_API_DECLARE(bool, set(double a, double b, double c)); // ax + by + c = 0
COM_API_DECLARE(void, from_points(const LPPOINT pt1, const LPPOINT pt2)); // (y - y0)/(y1 - y0) = (x - x0)/(x1 - x0)
COM_API_DECLARE(void, from_slope_intercepts(double k, double b)); // y = kx + b
COM_API_DECLARE(void, from_slope_point(double k, const LPPOINT pt)); // y - y1 = k(x - x1)
COM_API_DECLARE(void, from_intercepts(double a, double b)); // x / a + y / b = 1
COM_API_DECLARE(void, offset(double x_off = .0f, double y_off = .0f));
COM_API_DECLARE(double, A(void));
COM_API_DECLARE(double, B(void));
COM_API_DECLARE(double, C(void));
COM_API_DECLARE(double, x(double y)); // NOTE: if is horizontal, DO NOT call this !!!
COM_API_DECLARE(double, y(double x)); // NOTE: if is vertical, DO NOT call this !!!
COM_API_DECLARE(bool, is_vertical(void));
COM_API_DECLARE(bool, is_horizontal(void));
COM_API_DECLARE(double, slope(void)); // NOTE: if is vertical, DO NOT call this !!!
COM_API_DECLARE(double, x_intercept(void)); // NOTE: if is horizontal, DO NOT call this !!!
COM_API_DECLARE(double, y_intercept(void)); // NOTE: if is vertical, DO NOT call this !!!
COM_API_DECLARE(double, point_distance(const LPPOINT pt));
COM_API_DECLARE(bool, is_parallel(ILine* l));
COM_API_DECLARE(bool, crossing_point(ILine* l, LPPOINT pt)); // return false if is parallel, and the value in x and y is unreliable
COM_API_DECLARE(double, angle(void)); // in degree [0, 90]
COM_API_DECLARE(double, angle(ILine* l)); // in degree [0, 90]
COM_API_DECLARE(ILine*, normal_at(const LPPOINT pt));
};
__declspec(novtable) struct ICircle : public ref_util::IRef
{
COM_API_DECLARE(void, set_center(const LPPOINT pt));
COM_API_DECLARE(bool, set_radius(double r)); // must > 0
COM_API_DECLARE(double, circumference(void));
COM_API_DECLARE(double, area(void));
COM_API_DECLARE(const LPPOINT, center(void));
COM_API_DECLARE(double, radius(void));
COM_API_DECLARE(bool, is_point_in(const LPPOINT pt));
COM_API_DECLARE(bool, x(double y, double *bigger, double *smaller)); // return whether the line is intercourse with the circle
COM_API_DECLARE(bool, y(double x, double *bigger, double *smaller)); // return whether the line is intercourse with the circle
// pt & pt_another to receive the tangent point when return if pt was out of the circle
COM_API_DECLARE(ILine*, tangent(LPPOINT pt, ILine** another = NULL, LPPOINT pt_another = NULL));
COM_API_DECLARE(bool, tangent_point(ICircle* c, LPPOINT pt));
COM_API_DECLARE(ILine*, tangent(ICircle* c));
};
__declspec(novtable) struct IEllipse : public ref_util::IRef
{
COM_API_DECLARE(void, set_center(const LPPOINT pt));
COM_API_DECLARE(bool, set_radii(double rx, double ry)); // must > 0
COM_API_DECLARE(double, circumference(void));
COM_API_DECLARE(double, area(void));
COM_API_DECLARE(const LPPOINT, center(void));
COM_API_DECLARE(void, focuses(LPPOINT f1, LPPOINT f2));
COM_API_DECLARE(bool, is_point_in(const LPPOINT pt));
COM_API_DECLARE(bool, x(double y, double *bigger, double *smaller)); // return whether the line is intercourse with the circle
COM_API_DECLARE(bool, y(double x, double *bigger, double *smaller)); // return whether the line is intercourse with the circle
COM_API_DECLARE(ILine*, tangent(const LPPOINT pt)); // pt must on the circumference
};
PORT_API(ILine*) create_line(void);
PORT_API(ICircle*) create_circle(LPPOINT center, double radius);
PORT_API(IEllipse*) create_ellipse(LPPOINT center, double x_radius, double y_radius);
};