diff --git a/CHANGES b/CHANGES index 443b4cb..b56b723 100644 --- a/CHANGES +++ b/CHANGES @@ -126,6 +126,10 @@ The following are the changes from calc version 2.14.3.5 to date: builtin functions are listed by "show builtin" and the help/builtin to match the sorting of "LANG=C LC_ALL=C sort -d -u". + Added c_to_q(COMPLEX *c, bool cfree) to make is easier to convert + a COMPLEX value that is real (imag part is 0) into a NUMBER and + optionally free the COMPLEX value. + The following are the changes from calc version 2.14.3.4 to 2.14.3.5: diff --git a/LIBRARY b/LIBRARY index 438199c..71dd501 100644 --- a/LIBRARY +++ b/LIBRARY @@ -636,6 +636,23 @@ only used for complex numbers. Examples of macros are: There is only one comparison you can make for COMPLEX values, and that is for equality. The ccmp function returns true if two complex numbers differ. +Sometimes to results of a COMPLEX based calculation is a real number. +That is, the imaginary part of the COMPLEX is 0. You may convert the +COMPLEX into a new allocated NUMBER that is real part of the COMPLEX value. +For example: + + COMPLEX *c; + NUMBER *q; + bool ok_to_free; /* true ==> free COMPLEX value, false ==> do not */ + + if (cisreal(c)) { + q = c_to_q(c, ok_to_free); + } + +The 2nd argument to c_to_q() determines if the complex argument should be freed +or not. Pass a false value as the 2nd arg if you wish to continue to use the +COMPLEX value. + There are three predefined values for complex numbers. You should clink them when you want to use them. They are _czero_, _cone_, and _conei_. These have the values 0, 1, and i. diff --git a/cal/regress.cal b/cal/regress.cal index 07fbfee..73a71f6 100644 --- a/cal/regress.cal +++ b/cal/regress.cal @@ -3565,9 +3565,9 @@ define test_trig() ': round(aversin(0.5, 1e-10), 10) == 1.0471975512')); vrfy(aversin(0) == 0, strcat(str(tnum++), ': aversin(0) == 0')); - vrfy(round(aversin(-5, 1e-10), 10) == 0.1673829554+2.4921599676i, + vrfy(round(aversin(-5, 1e-10), 10) == 2.4778887303i, strcat(str(tnum++), - ': round(aversin(0.5, 1e-10), 10) == 0.1673829554+2.4921599676i')); + ': round(aversin(-5, 1e-10), 10) == 2.4778887303i')); vrfy(round(aversin(2 + 3i, 1e-10), 10) == 1.8783999763+1.8641615439i, strcat(str(tnum++), ': round(aversin(2 + 3i, 1e-10), 10) == 1.8783999763+1.8641615439i')); @@ -3578,9 +3578,9 @@ define test_trig() ': round(acoversin(0.5, 1e-10), 10) == 0.5235987756')); vrfy(acoversin(1) == 0, strcat(str(tnum++), ': acoversin(1) == 0')); - vrfy(round(acoversin(-5, 1e-10), 10) == 1.4034133718-2.4921599681i, + vrfy(round(acoversin(-5, 1e-10), 10) == 1.5707963268-2.4778887303i, strcat(str(tnum++), - ': round(acoversin(0.5, 1e-10), 10) == 1.4034133718-2.4921599681i')); + ': round(acoversin(-5, 1e-10), 10) == 1.5707963268-2.4778887303i')); vrfy(round(acoversin(2 + 3i, 1e-10), 10) == -0.3076036495-1.8641615442i, strcat(str(tnum++), ': round(acoversin(2 + 3i, 1e-10), 10) == -0.3076036495-1.8641615442i')); diff --git a/cmath.h b/cmath.h index 123bf49..9febb79 100644 --- a/cmath.h +++ b/cmath.h @@ -72,6 +72,7 @@ E_FUNC COMPLEX *c_shift(COMPLEX *c, long i); E_FUNC COMPLEX *c_square(COMPLEX *c); E_FUNC COMPLEX *c_conj(COMPLEX *c); E_FUNC COMPLEX *c_real(COMPLEX *c); +E_FUNC NUMBER *c_to_q(COMPLEX *c, bool cfree); E_FUNC COMPLEX *c_imag(COMPLEX *c); E_FUNC COMPLEX *c_neg(COMPLEX *c); E_FUNC COMPLEX *c_inv(COMPLEX *c); diff --git a/commath.c b/commath.c index c876ec7..5fa9f02 100644 --- a/commath.c +++ b/commath.c @@ -396,6 +396,65 @@ c_real(COMPLEX *c) } +/* + * c_to_q - convert a real part of a COMPLEX to a NUMBER + * + * given: + * c complex number for which the real part will be used + * cfree true ==> free c, false ==> do not free c + * + * returns: + * allocated NUMBER that the equivalent of the real part of a complex number + * + * NOTE: Any imaginary part of the COMPLEX value is ignored. + * + * NOTE: To avoid a loss of value, test with cisreal(c) first: + * + * COMPLEX *c; + * NUMBER *q; + * bool ok_to_free; + * + * if (cisreal(c)) { + * q = c_to_q(c, ok_to_free); + * } + */ +NUMBER * +c_to_q(COMPLEX *c, bool cfree) +{ + NUMBER *r; /* allocated NUMBER equivalent to return */ + + /* + * firewall + */ + if (c == NULL) { + math_error("%s: c is NULL", __func__); + not_reached(); + } + + /* + * allocate a new NUMBER + */ + r = qalloc(); + + /* + * link in the real part of the COMPLEX value + */ + r = qlink(c->real); + + /* + * free c if requested + */ + if (cfree == true) { + comfree(c); + } + + /* + * return the allocated equivalent NUMBER + */ + return r; +} + + /* * Return the imaginary part of a complex number as a real. */ diff --git a/func.c b/func.c index e74e500..910435b 100644 --- a/func.c +++ b/func.c @@ -2140,9 +2140,8 @@ f_exp(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } break; default: @@ -2202,9 +2201,8 @@ f_ln(int count, VALUE **vals) result.v_type = V_COM; result.v_com = c; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } return result; } @@ -2263,9 +2261,8 @@ f_log(int count, VALUE **vals) result.v_type = V_COM; result.v_com = c; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } return result; } @@ -2324,9 +2321,8 @@ f_log2(int count, VALUE **vals) result.v_type = V_COM; result.v_com = c; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } return result; } @@ -2409,8 +2405,7 @@ f_logn(int count, VALUE **vals) return error_value(E_LOGN_3); } if (cisreal(ln_x_c)) { - ln_x_r = qcopy(ln_x_c->real); - comfree(ln_x_c); + ln_x_r = c_to_q(ln_x_c, true); } else { ln_of_x_is_complex = true; } @@ -2430,8 +2425,7 @@ f_logn(int count, VALUE **vals) return error_value(E_LOGN_3); } if (cisreal(ln_x_c)) { - ln_x_r = qcopy(ln_x_c->real); - comfree(ln_x_c); + ln_x_r = c_to_q(ln_x_c, true); } else { ln_of_x_is_complex = true; } @@ -2464,8 +2458,7 @@ f_logn(int count, VALUE **vals) return error_value(E_LOGN_4); } if (cisreal(ln_n_c)) { - ln_n_r = qcopy(ln_n_c->real); - comfree(ln_n_c); + ln_n_r = c_to_q(ln_n_c, true); } else { ln_of_n_is_complex = true; } @@ -2493,8 +2486,7 @@ f_logn(int count, VALUE **vals) return error_value(E_LOGN_4); } if (cisreal(ln_n_c)) { - ln_n_r = qcopy(ln_n_c->real); - comfree(ln_n_c); + ln_n_r = c_to_q(ln_n_c, true); } else { ln_of_n_is_complex = true; } @@ -2519,9 +2511,8 @@ f_logn(int count, VALUE **vals) /* check if division is COMPLEX or NUMBER */ if (cisreal(p_cval)) { /* ln(x) / ln(n) was NUMBER, not COMPLEX */ - result.v_num = qlink(p_cval->real); + result.v_num = c_to_q(p_cval, true); result.v_type = V_NUM; - comfree(p_cval); } else { /* ln(x) / ln(n) is COMPLEX */ result.v_type = V_COM; @@ -2540,9 +2531,8 @@ f_logn(int count, VALUE **vals) /* check if division is COMPLEX or NUMBER */ if (cisreal(p_cval)) { /* ln(x) / ln(n) was NUMBER, not COMPLEX */ - result.v_num = qlink(p_cval->real); + result.v_num = c_to_q(p_cval, true); result.v_type = V_NUM; - comfree(p_cval); } else { /* ln(x) / ln(n) is COMPLEX */ result.v_type = V_COM; @@ -2567,9 +2557,8 @@ f_logn(int count, VALUE **vals) /* check if division is COMPLEX or NUMBER */ if (cisreal(p_cval)) { /* ln(x) / ln(n) was NUMBER, not COMPLEX */ - result.v_num = qlink(p_cval->real); + result.v_num = c_to_q(p_cval, true); result.v_type = V_NUM; - comfree(p_cval); } else { /* ln(x) / ln(n) is COMPLEX */ result.v_type = V_COM; @@ -2633,9 +2622,8 @@ f_cos(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } break; default: @@ -2945,9 +2933,8 @@ f_sin(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } break; default: @@ -3208,8 +3195,7 @@ f_sinh(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); - comfree(c); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; } break; @@ -3262,8 +3248,7 @@ f_cosh(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); - comfree(c); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; } break; @@ -3524,9 +3509,8 @@ f_atan(int count, VALUE **vals) result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { - result.v_num = qlink(tmp->real); + result.v_num = c_to_q(tmp, true); result.v_type = V_NUM; - comfree(tmp); } break; default: @@ -3574,9 +3558,8 @@ f_acot(int count, VALUE **vals) result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { - result.v_num = qlink(tmp->real); + result.v_num = c_to_q(tmp, true); result.v_type = V_NUM; - comfree(tmp); } break; default: @@ -3591,7 +3574,6 @@ f_asin(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3636,10 +3618,8 @@ f_asin(int count, VALUE **vals) return error_value(E_ASIN3); } if (result.v_type == V_COM && cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } return result; } @@ -3650,7 +3630,6 @@ f_acos(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3695,10 +3674,8 @@ f_acos(int count, VALUE **vals) return error_value(E_ACOS3); } if (result.v_type == V_COM && cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } return result; } @@ -3710,7 +3687,6 @@ f_asec(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3758,10 +3734,8 @@ f_asec(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -3774,7 +3748,6 @@ f_acsc(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3822,10 +3795,8 @@ f_acsc(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -3871,9 +3842,8 @@ f_asinh(int count, VALUE **vals) result.v_type = V_COM; result.v_com = tmp; if (cisreal(tmp)) { - result.v_num = qlink(tmp->real); + result.v_num = c_to_q(tmp, true); result.v_type = V_NUM; - comfree(tmp); } break; default: @@ -3889,7 +3859,6 @@ f_acosh(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3934,10 +3903,8 @@ f_acosh(int count, VALUE **vals) return error_value(E_ACOSH3); } if (result.v_type == V_COM && cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } return result; } @@ -3949,7 +3916,6 @@ f_atanh(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -3995,10 +3961,8 @@ f_atanh(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -4011,7 +3975,6 @@ f_acoth(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -4057,10 +4020,8 @@ f_acoth(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -4073,7 +4034,6 @@ f_asech(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -4121,10 +4081,8 @@ f_asech(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -4137,7 +4095,6 @@ f_acsch(int count, VALUE **vals) VALUE result; COMPLEX *tmp; NUMBER *err; - NUMBER *q; /* initialize VALUE */ result.v_subtype = V_NOSUBTYPE; @@ -4185,10 +4142,8 @@ f_acsch(int count, VALUE **vals) } if (result.v_type == V_COM) { if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; - result.v_num = q; } } return result; @@ -4200,7 +4155,6 @@ f_gd(int count, VALUE **vals) { VALUE result; NUMBER *eps; - NUMBER *q; COMPLEX *tmp; /* initialize VALUE */ @@ -4245,9 +4199,7 @@ f_gd(int count, VALUE **vals) if (result.v_com == NULL) return error_value(E_GD3); if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); - result.v_num = q; + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; } return result; @@ -4259,7 +4211,6 @@ f_agd(int count, VALUE **vals) { VALUE result; NUMBER *eps; - NUMBER *q; COMPLEX *tmp; /* initialize VALUE */ @@ -4304,9 +4255,7 @@ f_agd(int count, VALUE **vals) if (result.v_com == NULL) return error_value(E_AGD3); if (cisreal(result.v_com)) { - q = qlink(result.v_com->real); - comfree(result.v_com); - result.v_num = q; + result.v_num = c_to_q(result.v_com, true); result.v_type = V_NUM; } return result; @@ -5974,9 +5923,8 @@ f_polar(int count, VALUE **vals) result.v_com = c; result.v_type = V_COM; if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } return result; } @@ -10660,9 +10608,8 @@ f_versin(int count, VALUE **vals) * case: complex trig function returned real, convert result to NUMBER */ if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } break; default: @@ -10717,7 +10664,8 @@ f_aversin(int count, VALUE **vals) */ } else { /* convert NUMBER argument from NUMBER to COMPLEX */ - vals[0]->v_com = qqtoc(vals[0]->v_num, &_qone_); + /* XXX - WRONG - do not change the arg! */ + vals[0]->v_com = qqtoc(vals[0]->v_num, &_qzero_); vals[0]->v_type = V_COM; } } @@ -10738,9 +10686,8 @@ f_aversin(int count, VALUE **vals) * case: complex trig function returned real, convert result to NUMBER */ if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } } if (vals[0]->v_type != V_NUM && vals[0]->v_type != V_COM) { @@ -10800,9 +10747,8 @@ f_coversin(int count, VALUE **vals) * case: complex trig function returned real, convert result to NUMBER */ if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } break; default: @@ -10857,7 +10803,8 @@ f_acoversin(int count, VALUE **vals) */ } else { /* convert NUMBER argument from NUMBER to COMPLEX */ - vals[0]->v_com = qqtoc(vals[0]->v_num, &_qone_); + /* XXX - WRONG - do not change the arg! */ + vals[0]->v_com = qqtoc(vals[0]->v_num, &_qzero_); vals[0]->v_type = V_COM; } } @@ -10878,9 +10825,8 @@ f_acoversin(int count, VALUE **vals) * case: complex trig function returned real, convert result to NUMBER */ if (cisreal(c)) { - result.v_num = qlink(c->real); + result.v_num = c_to_q(c, true); result.v_type = V_NUM; - comfree(c); } } if (vals[0]->v_type != V_NUM && vals[0]->v_type != V_COM) { diff --git a/help/acoversin b/help/acoversin index 72643a6..1728af6 100644 --- a/help/acoversin +++ b/help/acoversin @@ -24,7 +24,7 @@ EXAMPLE 0.5236 0.5235987756 0.523598775598299 0.52359877559829887308 ; print acoversin(1), acoversin(-5), acoversin(2 + 3i) - 0 1.40341337183925787843-2.49215996813383545614i -0.30760364953071124992-1.86416154415788242834i + 0 1.57079632679489661923-2.47788873028847500481i -0.30760364953071124992-1.86416154415788242834i LIMITS 0 < eps < 1 diff --git a/help/aversin b/help/aversin index 25ac632..789d9b4 100644 --- a/help/aversin +++ b/help/aversin @@ -24,7 +24,7 @@ EXAMPLE 1.0472 1.0471975512 1.047197551196598 1.04719755119659774615 ; print aversin(0), aversin(-5), aversin(2 + 3i) - 0 0.16738295495563874081+2.49215996813383545614i 1.87839997632560786916+1.86416154415788242831i + 0 2.47788873028847500485i 1.87839997632560786916+1.86416154415788242831i LIMITS 0 < eps < 1