diff options
Diffstat (limited to 'Build/source')
-rw-r--r-- | Build/source/texk/web2c/mplibdir/mp.w | 530 | ||||
-rw-r--r-- | Build/source/texk/web2c/mplibdir/mpmathbinary.w | 18 | ||||
-rw-r--r-- | Build/source/texk/web2c/mplibdir/mpmathdecimal.w | 36 | ||||
-rw-r--r-- | Build/source/texk/web2c/mplibdir/mpmathdouble.w | 25 |
4 files changed, 523 insertions, 86 deletions
diff --git a/Build/source/texk/web2c/mplibdir/mp.w b/Build/source/texk/web2c/mplibdir/mp.w index 107fdcd368f..431af9f4e92 100644 --- a/Build/source/texk/web2c/mplibdir/mp.w +++ b/Build/source/texk/web2c/mplibdir/mp.w @@ -1,4 +1,4 @@ -% $Id: mp.w 2089 2016-08-22 09:42:23Z luigi $ +% $Id: mp.w 2091 2016-09-16 23:07:58Z luigi $ % % This file is part of MetaPost; % the MetaPost program is in the public domain. @@ -140,6 +140,19 @@ typedef struct MP_instance { #endif @ @c +/*#define DEBUGENVELOPE */ +#ifdef DEBUGENVELOPE +#define dbg_n(A) printf("['%s']=%s, ", #A, number_tostring(A)) +#define dbg_in(A) printf("['%s']=%d, ", #A, (int)(A)) +#define dbg_dn(A) printf("['%s']=%.100f, ", #A, (double)(A)) +#define dbg_key(A) printf("['%s']= ", #A) +#define dbg_sp printf(" ") +#define dbg_str(A) printf("%s",#A) +#define dbg_open_t printf("{") +#define dbg_close_t printf("}") +#define dbg_comma printf(",") +#define dbg_nl printf("\n") +#endif #define KPATHSEA_DEBUG_H 1 #include <w2c/config.h> #include <stdio.h> @@ -171,6 +184,15 @@ typedef struct MP_instance { #include "mpmathdecimal.h" /* internal header */ #include "mpmathbinary.h" /* internal header */ #include "mpstrings.h" /* internal header */ +/* BEGIN PATCH */ +mp_number dx_ap; /* approximation of dx */ +mp_number dy_ap; /* approximation of dy */ +mp_number dxin_ap; /* approximation of dxin */ +mp_number dyin_ap; /* approximation of dyin */ +mp_number ueps_ap; /* epsilon for above approximations */ +/* END PATCH */ + + extern font_number mp_read_font_info (MP mp, char *fname); /* tfmin.w */ @h @<Declarations@>; @<Basic printing procedures@>; @@ -2568,18 +2590,18 @@ void mp_new_randoms (MP mp) { mp->j_random = 54; } -@ To consume a random fraction, the program below will say `|next_random|'. +@ To consume a random fraction, the program below will say `|next_random|'. Now each number system has its own implementation, true to the original as much as possibile. @c /* Unused. -static void mp_next_random (MP mp, mp_number *ret) { - if ( mp->j_random==0 ) - mp_new_randoms(mp); +static void mp\_next\_random (MP mp, mp\_number *ret) { + if ( mp->j\_random==0 ) + mp\_new\_randoms(mp); else - decr(mp->j_random); - number_clone (*ret, mp->randoms[mp->j_random]); + decr(mp->j\_random); + number\_clone (*ret, mp->randoms[mp->j\_random]); } */ @@ -2596,31 +2618,31 @@ As said before, now each number system has its own implementation. @c /*Unused. -static void mp_unif_rand (MP mp, mp_number *ret, mp_number x_orig) { - mp_number y; // trial value - mp_number x, abs_x; - mp_number u; - new_fraction (y); - new_number (x); - new_number (abs_x); - new_number (u); - number_clone (x, x_orig); - number_clone (abs_x, x); - number_abs (abs_x); - mp_next_random(mp, &u); - take_fraction (y, abs_x, u); - free_number (u); - if (number_equal(y, abs_x)) { - set_number_to_zero(*ret); - } else if (number_positive(x)) { - number_clone (*ret, y); +static void mp\_unif\_rand (MP mp, mp\_number *ret, mp\_number x\_orig) { + mp\_number y; // trial value + mp\_number x, abs\_x; + mp\_number u; + new\_fraction (y); + new\_number (x); + new\_number (abs\_x); + new\_number (u); + number\_clone (x, x\_orig); + number\_clone (abs\_x, x); + number\_abs (abs\_x); + mp\_next\_random(mp, \&u); + take\_fraction (y, abs\_x, u); + free\_number (u); + if (number\_equal(y, abs\_x)) { + set\_number\_to\_zero(*ret); + } else if (number\_positive(x)) { + number\_clone (*ret, y); } else { - number_clone (*ret, y); - number_negate (*ret); + number\_clone (*ret, y); + number\_negate (*ret); } - free_number (abs_x); - free_number (x); - free_number (y); + free\_number (abs\_x); + free\_number (x); + free\_number (y); } */ @@ -2634,43 +2656,43 @@ true to the original as much as possibile. @c /* Unused. -static void mp_norm_rand (MP mp, mp_number *ret) { - mp_number ab_vs_cd; - mp_number abs_x; - mp_number u; - mp_number r; - mp_number la, xa; - new_number (ab_vs_cd); - new_number (la); - new_number (xa); - new_number (abs_x); - new_number (u); - new_number (r); +static void mp\_norm\_rand (MP mp, mp\_number *ret) { + mp\_number ab\_vs\_cd; + mp\_number abs\_x; + mp\_number u; + mp\_number r; + mp\_number la, xa; + new\_number (ab\_vs\_cd); + new\_number (la); + new\_number (xa); + new\_number (abs\_x); + new\_number (u); + new\_number (r); do { do { - mp_number v; - new_number (v); - mp_next_random(mp, &v); - number_substract (v, fraction_half_t); - take_fraction (xa, sqrt_8_e_k, v); - free_number (v); - mp_next_random(mp, &u); - number_clone (abs_x, xa); - number_abs (abs_x); - } while (number_greaterequal (abs_x, u)); - make_fraction (r, xa, u); - number_clone (xa, r); - m_log (la, u); - set_number_from_substraction(la, twelve_ln_2_k, la); - ab_vs_cd (ab_vs_cd, one_k, la, xa, xa); - } while (number_negative(ab_vs_cd)); - number_clone (*ret, xa); - free_number (ab_vs_cd); - free_number (r); - free_number (abs_x); - free_number (la); - free_number (xa); - free_number (u); + mp\_number v; + new\_number (v); + mp\_next\_random(mp, \&v); + number\_substract (v, fraction\_half\_t); + take\_fraction (xa, sqrt\_8\_e\_k, v); + free\_number (v); + mp\_next\_random(mp, \&u); + number\_clone (abs\_x, xa); + number\_abs (abs\_x); + } while (number\_greaterequal (abs\_x, u)); + make\_fraction (r, xa, u); + number\_clone (xa, r); + m\_log (la, u); + set\_number\_from\_substraction(la, twelve\_ln\_2\_k, la); + ab\_vs\_cd (ab\_vs\_cd, one\_k, la, xa, xa); + } while (number\_negative(ab\_vs\_cd)); + number\_clone (*ret, xa); + free\_number (ab\_vs\_cd); + free\_number (r); + free\_number (abs\_x); + free\_number (la); + free\_number (xa); + free\_number (u); } */ @@ -4705,7 +4727,7 @@ static mp_sym mp_frozen_id_lookup (MP mp, char *j, size_t l, return mp_do_id_lookup (mp, mp->frozen_symbols, j, l, insert_new); } -/* see mp_print_sym (mp_sym sym) */ +/* see mp\_print\_sym (mp\_sym sym) */ @ Get a numeric value from \MP\ is not easy. We have to consider the macro and the loops, as also the internal type (this is a first attempt, and more work is needed). If we are inside @@ -13144,6 +13166,118 @@ Since an envelope spec only determines relative changes in pen offsets, @<Glob...@>= integer spec_offset; /* number of pen edges between |h| and the initial offset */ +@ The next function calculates $1/3 B'(t) = (-p + (3*c1 + (-3*c2 + q)))*t^2 + (2*p + (-4*c1 + 2*c2))*t + (-p + c1)$, +and it's used for |t| near 0 and |t| near 1. + +@<Declarations@>= +static void mp_dx_dy_approx(MP mp, mp_number *dx_ap, mp_number *dy_ap,mp_knot p, mp_knot q,mp_number t); + +@ @c +static void mp_dx_dy_approx(MP mp, mp_number *dx_ap, mp_number *dy_ap,mp_knot kp, mp_knot kq,mp_number t) { /* find dx dy at |t| */ + + /* 1/3 B'(t) = (-p + (3c1 + (-3c2 + q)))t^2 + (2p + (-4c1 + 2c2))*t + (-p + c1) */ + mp_number p,c1,c2,q; + mp_number s1,s2,s3; + mp_number absval; + mp_number max_coef; /* used while scaling */ + mp_number small_nr, big_nr; + mp_number abs_dx, abs_dy; + + new_number(p); + new_number(c1); + new_number(c2); + new_number(q); + new_number(s1); + new_number(s2); + new_number(s3); + new_number (absval); + new_number(max_coef); + new_number(small_nr); + new_number(big_nr); + new_number(abs_dx); + new_number(abs_dy); + + set_number_from_double(small_nr,0.001); + set_number_from_double(big_nr,1000); + + number_clone (p,kp->x_coord); + number_clone (c1,kp->right_x); + number_clone (c2,kq->left_x); + number_clone (q,kq->x_coord); + + number_clone (s1,p); + number_negate (s1); + number_add (s1,c1);number_add (s1,c1);number_add (s1,c1); + number_substract(s1,c2);number_substract (s1,c2);number_substract (s1,c2); + number_add (s1,q); + set_number_from_mul(s1,s1,t);set_number_from_mul(s1,s1,t); + number_clone (s2,p); number_add (s2,p); + number_substract(s2,c1);number_substract (s2,c1);number_substract (s2,c1);number_substract (s2,c1); + number_add (s2,c2);number_add (s2,c2); + set_number_from_mul (s2,s2,t); + number_clone (s3,c1); + number_substract(s3,p); + number_add (s3,s2); + number_add (s3,s1); + number_clone(*dx_ap,s3); + + number_clone(p,kp->y_coord); + number_clone(c1,kp->right_y); + number_clone(c2,kq->left_y); + number_clone(q,kq->y_coord); + + number_clone (s1,p); + number_negate (s1); + number_add (s1,c1);number_add (s1,c1);number_add (s1,c1); + number_substract(s1,c2);number_substract (s1,c2);number_substract (s1,c2); + number_add (s1,q); + set_number_from_mul(s1,s1,t);set_number_from_mul(s1,s1,t); + number_clone (s2,p); number_add (s2,p); + number_substract(s2,c1);number_substract (s2,c1);number_substract (s2,c1);number_substract (s2,c1); + number_add (s2,c2);number_add (s2,c2); + set_number_from_mul (s2,s2,t); + number_clone (s3,c1); + number_substract(s3,p); + number_add (s3,s2); + number_add (s3,s1); + number_clone(*dy_ap,s3); + + + if (!number_zero(*dx_ap) || !number_zero(*dy_ap)) { + number_clone(absval, *dx_ap); + number_abs(absval); + number_clone(max_coef, *dy_ap); + number_abs (max_coef); + if (number_greater(absval, max_coef)) { + number_clone(max_coef, absval); + } + while (number_less(max_coef, fraction_half_t)) { + number_double (max_coef); + number_double (*dx_ap); + number_double (*dy_ap); + } + number_clone(abs_dx,*dx_ap); + number_clone(abs_dy,*dy_ap); + number_abs(abs_dx); + number_abs(abs_dy); + /* This is an experimental approximation */ + /* We should put a warning here */ + if (number_greaterequal(abs_dy,big_nr) && number_lessequal(abs_dx,small_nr)) { + set_number_to_zero(*dx_ap); + } + if (number_greaterequal(abs_dx,big_nr) && number_lessequal(abs_dy,small_nr)) { + set_number_to_zero(*dy_ap); + } + } + free_number(p); + free_number(c1); + free_number(c2); + free_number(q); + free_number(s1); + free_number(s2); + free_number(s3); +} + @ @c static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { int n; /* the number of vertices in the pen polygon */ @@ -13183,6 +13317,13 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { new_number(u1); new_number(v0); new_number(v1); + new_number(dx_m); + new_number(dxin_m); + new_number(dx_ap); + new_number(dy_ap); + new_number(dxin_ap); + new_number(dyin_ap); + new_number(ueps_ap); new_fraction (ss); new_fraction (s); new_fraction (t); @@ -13191,17 +13332,39 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { p = c; c0 = c; k_needed = 0; - do { +#ifdef DEBUGENVELOPE +dbg_nl;dbg_str(--[==[BEGIN]==]);dbg_nl; +#endif + do { q = mp_next_knot (p); +#ifdef DEBUGENVELOPE +dbg_nl;dbg_open_t;dbg_str(--[==[begin loop]==]);dbg_nl; +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif @<Split the cubic between |p| and |q|, if necessary, into cubics associated with single offsets, after which |q| should point to the end of the final such cubic@>; NOT_FOUND: @<Advance |p| to node |q|, removing any ``dead'' cubics that might have been introduced by the splitting process@>; +#ifdef DEBUGENVELOPE +dbg_str(--[==[end loop]==]);dbg_nl; dbg_close_t;dbg_comma;dbg_nl; +#endif } while (q != c); +#ifdef DEBUGENVELOPE + dbg_key(Fix the offset change);dbg_open_t;dbg_nl; + dbg_in(mp_knot_info(p));dbg_close_t;dbg_comma;dbg_nl; +#endif @<Fix the offset change in |mp_knot_info(c)| and set |c| to the return value of |offset_prep|@>; +#ifdef DEBUGENVELOPE +dbg_in(mp_knot_info(p)); +dbg_close_t;dbg_comma;dbg_nl; +dbg_nl;dbg_str(--[==[END]==]);dbg_nl; +#endif free_number (ss); free_number (s); free_number (dxin); @@ -13232,6 +13395,13 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { free_number (u1); free_number (v0); free_number (v1); + free_number(dx_m); + free_number(dxin_m); + free_number(dx_ap); + free_number(dy_ap); + free_number(dxin_ap); + free_number(dyin_ap); + free_number(ueps_ap); free_number (t); return c; } @@ -13447,6 +13617,9 @@ mp_number dx0, dy0; /* initial direction for the first cubic in the curve mp_number x0a, x1a, x2a, y0a, y1a, y2a; /* intermediate values */ mp_number t; /* where the derivative passes through zero */ mp_number s; /* a temporary value */ +mp_number dx_m; /* signal a pertubation of dx */ +mp_number dxin_m; /* signal a pertubation of dxin */ + @ @<Prepare for derivative computations...@>= set_number_from_substraction(x0, p->right_x, p->x_coord); @@ -13455,6 +13628,11 @@ set_number_from_substraction(x1, q->left_x, p->right_x); set_number_from_substraction(y0, p->right_y, p->y_coord); set_number_from_substraction(y2, q->y_coord, q->left_y); set_number_from_substraction(y1, q->left_y, p->right_y); +#ifdef DEBUGENVELOPE +dbg_key(Prepare for derivative computations);dbg_open_t;dbg_nl; +dbg_n(x0);dbg_n(y0);dbg_n(x1);dbg_n(y1);dbg_n(x2);dbg_n(y2); +dbg_close_t;dbg_comma;dbg_nl; +#endif { mp_number absval; new_number (absval); @@ -13698,6 +13876,7 @@ the true initial direction for the given cubic, even if it is almost degenerate. @<Find the initial direction |(dx,dy)|@>= +number_clone(dx_m, zero_t); number_clone(dx, x0); number_clone(dy, y0); if (number_zero(dx) && number_zero(dy)) { @@ -13712,8 +13891,71 @@ if (p == c) { number_clone(dx0, dx); number_clone(dy0, dy); } +/* BEGIN PATCH */ +set_number_from_substraction(ueps_ap,unity_t,epsilon_t); /* |1-eps| */ +#ifdef DEBUGENVELOPE +dbg_nl;dbg_key(mp_dx_dy_approx_t_1);dbg_open_t;dbg_nl; +dbg_n(ueps_ap); +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif +mp_dx_dy_approx(mp,&dxin_ap,&dyin_ap,p,q,ueps_ap); +#ifdef DEBUGENVELOPE +dbg_n(dxin_ap);dbg_n(dyin_ap); +dbg_close_t;dbg_comma;dbg_nl; +#endif +/**/ +number_clone(ueps_ap,epsilon_t); +#ifdef DEBUGENVELOPE +dbg_nl;dbg_key(mp_dx_dy_approx_t_0);dbg_open_t;dbg_nl; +dbg_n(ueps_ap); +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif +mp_dx_dy_approx(mp,&dx_ap,&dy_ap,p,q,ueps_ap); /*|eps|*/ +#ifdef DEBUGENVELOPE +dbg_n(dx_ap);dbg_n(dy_ap); +dbg_close_t;dbg_comma;dbg_nl; +dbg_key(derivatives);dbg_open_t;dbg_nl; +dbg_n(dx);dbg_n(dy);dbg_n(dx_ap);dbg_n(dy_ap);dbg_close_t;dbg_comma;dbg_nl; +#endif +/* BEGIN PATCH */ +if (number_zero(dx) && !(number_zero(dy)) && number_zero(x0) && number_zero(x2) && !number_zero(dxin) ){ + number_clone(dx_m, epsilon_t); + if (number_positive(x1)){ + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x1)) { + set_number_from_substraction (dx, dx, epsilon_t); + } +} +/* hm what about dx=dy=0 ? */ +if (number_zero(dx_ap) && !number_zero(dx)){ + set_number_to_zero(dx); + if (p == c) { + set_number_to_zero(dx0); + } + mp_warn(mp,"x component of derivative at t=0 approximated to zero."); + } +if (number_zero(dy_ap) && !number_zero(dy)){ + set_number_to_zero(dy); + if (p == c) { + set_number_to_zero(dy0); + } + mp_warn(mp,"y component of derivative at t=0 approximated to zero."); + } +#ifdef DEBUGENVELOPE +dbg_key(derivatives patched);dbg_open_t;dbg_nl; +dbg_n(dx);dbg_n(dy);dbg_n(dx_ap);dbg_n(dy_ap);dbg_close_t;dbg_comma;dbg_nl; +#endif +/* END PATCH */ + @ @<Find the final direction |(dxin,dyin)|@>= +number_clone(dxin_m, zero_t); number_clone(dxin, x2); number_clone(dyin, y2); if (number_zero(dxin) && number_zero(dyin)) { @@ -13724,6 +13966,45 @@ if (number_zero(dxin) && number_zero(dyin)) { number_clone(dyin, y0); } } +if (number_zero(dxin_ap) && !number_zero(dxin)){ + set_number_to_zero(dxin); + mp_warn(mp,"x component of derivative at t=1 approximated at zero"); + } +if (number_zero(dyin_ap) && !number_zero(dyin)){ + set_number_to_zero(dyin); + mp_warn(mp,"y component of derivative at t=1 approximated at zero"); + } +#ifdef DEBUGENVELOPE +dbg_key(dxin dyin);dbg_open_t;dbg_nl; +dbg_n(dxin);dbg_n(dyin); +dbg_close_t;dbg_comma; +#endif +/* BEGIN PATCH \par +$ 1/3 B'(t,X_0,X_1,X_2) = (1-t)^2X_0+2(1-t)tX_1+3t^2X_2 $ \par +$ 1/3 B'(t,X_0,X_1,X_2) = (X_0 + (-2X_1 + X_2))t^2 + (-2X_0 + 2X_1)t + X_0 $ \par +$ 1/3 B'(s,0,X_1,0) = (-2s^2 + 2s)X_1 \approx 2sX_1 $ for $s\rightarrow 0$ \par +$ 1/3 B'(1-s,0,X_1,0) = (-2s^2 + 2s)X_1 \approx 2sX_1 $ for $s\rightarrow 0$ $\par +*/ +/* Of course the same should be done for dy and dyin */ +if ( ((number_zero(dx)||number_positive(dx_m)) && number_positive(dy)) && + (number_zero(dxin) && number_positive(dyin)) ){ + number_clone(dx_m, epsilon_t); + number_clone(dxin_m, epsilon_t); + if (number_positive(x1)){ + set_number_from_addition (dxin, dxin, epsilon_t); + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x1)) { + set_number_from_substraction (dxin, dxin, epsilon_t); + set_number_from_substraction (dx, dx, epsilon_t); + } else if (number_positive(x0)) { + set_number_from_addition (dxin, dxin, epsilon_t); + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x0)) { + set_number_from_substraction (dxin, dxin, epsilon_t); + set_number_from_substraction (dx, dx, epsilon_t); + } +} +/* END PATCH ****/ @ The next step is to bracket the initial direction between consecutive edges of the pen polygon. We must be careful to turn clockwise only if @@ -13737,11 +14018,35 @@ right.) This code depends on |w0| being the offset for |(dxin,dyin)|. mp_number ab_vs_cd; new_number (ab_vs_cd); ab_vs_cd (ab_vs_cd, dy, dxin, dx, dyin); - turn_amt = mp_get_turn_amt (mp, w0, dx, dy, number_nonnegative(ab_vs_cd)); +#ifdef DEBUGENVELOPE +dbg_nl; +dbg_key(mp_get_turn_amt_dx_dy);dbg_open_t;dbg_str(--[==[call mp_get_turn_amt]==]);dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord);dbg_n(dx);dbg_n(dy);dbg_in(number_nonnegative(ab_vs_cd)); +#endif + turn_amt = mp_get_turn_amt (mp, w0, dx, dy, number_nonnegative(ab_vs_cd)); +#ifdef DEBUGENVELOPE +dbg_dn(turn_amt); +dbg_close_t;dbg_comma; +dbg_nl; +#endif free_number (ab_vs_cd); +#ifdef DEBUGENVELOPE +dbg_key(w0 before walk);dbg_open_t;dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord); +dbg_close_t;dbg_comma; +#endif w = mp_pen_walk (mp, w0, turn_amt); w0 = w; +#ifdef DEBUGENVELOPE +dbg_key(w0 after walk);dbg_open_t;dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord); +dbg_close_t;dbg_comma; +dbg_open_t;dbg_in(mp_knot_info(p)); +#endif mp_knot_info (p) = mp_knot_info (p) + turn_amt; +#ifdef DEBUGENVELOPE + dbg_in(mp_knot_info(p));dbg_close_t;dbg_comma; +#endif } @ Decide how many pen offsets to go away from |w| in order to find the offset @@ -13762,18 +14067,42 @@ integer mp_get_turn_amt (MP mp, mp_knot w, mp_number dx, mp_number dy, boolean c mp_knot ww; /* a neighbor of knot~|w| */ integer s; /* turn amount so far */ mp_number t; /* |ab_vs_cd| result */ + mp_number t_ap; /* |ab_vs_cd| approx. result */ mp_number arg1, arg2; s = 0; new_number (arg1); new_number (arg2); new_number (t); + new_number (t_ap); if (ccw) { ww = mp_next_knot (w); do { set_number_from_substraction (arg1, ww->x_coord, w->x_coord); set_number_from_substraction (arg2, ww->y_coord, w->y_coord); ab_vs_cd (t, dy, arg1, dx, arg2); - if (number_negative(t)) +#ifdef DEBUGENVELOPE + dbg_sp; + dbg_open_t;dbg_str(--[==[inside mp_get_turn_amt do loop ]==]);dbg_nl; + dbg_n(w->x_coord);dbg_n(w->y_coord);dbg_n(ww->x_coord);dbg_n(ww->y_coord); + dbg_n(t);dbg_n(dy);dbg_n(arg1);dbg_n(dx);dbg_n(arg2); + dbg_n(t_ap);dbg_n(dy_ap);dbg_n(dx_ap); + dbg_close_t;dbg_comma; + dbg_nl; +#endif + /* BEGIN PATCH */ + if (number_zero(dx) && number_zero(arg1) && number_positive(dy) && number_positive(arg2)) + break; + if (number_zero(dx) && number_zero(arg1) && number_negative(dy) && number_negative(arg2)) + break; + if (number_zero(dy) && number_zero(arg2) && number_negative(dx) && number_negative(arg1)) + break; + if (number_zero(dx) && number_zero(arg1) && number_negative(dy) && number_positive(arg2)) + set_number_to_unity(t); + if (number_zero(dy) && number_zero(arg2) && number_positive(dx) && number_negative(arg1)) + set_number_to_unity(t); + + /* END PATCH */ + if (number_negative(t)) break; incr (s); w = ww; @@ -13794,6 +14123,7 @@ integer mp_get_turn_amt (MP mp, mp_knot w, mp_number dx, mp_number dy, boolean c } } free_number (t); + free_number (t_ap); free_number (arg1); free_number (arg2); return s; @@ -13950,8 +14280,18 @@ the path should always change the sign of |turn_amt|. @<Decide on the net change in pen offsets and set |turn_amt|@>= { mp_number ab_vs_cd; + mp_number t_ap; + new_number (t_ap); new_number (ab_vs_cd); +#ifdef DEBUGENVELOPE +dbg_sp; +dbg_key(Decide on the net change in pen offsets and set turn_amt);dbg_open_t;dbg_nl; +#endif ab_vs_cd (ab_vs_cd, dx, dyin, dxin, dy); +#ifdef DEBUGENVELOPE +dbg_n(ab_vs_cd);dbg_n(dx);dbg_n(dyin);dbg_n(dxin);dbg_n(dy); +dbg_close_t;dbg_comma;dbg_nl; +#endif if (number_negative (ab_vs_cd)) d_sign = -1; else if (number_zero (ab_vs_cd)) @@ -13959,6 +14299,7 @@ the path should always change the sign of |turn_amt|. else d_sign = 1; free_number (ab_vs_cd); + free_number (t_ap); } if (d_sign == 0) { @<Check rotation direction based on node position@> @@ -13978,7 +14319,16 @@ if (d_sign == 0) { } @<Make |ss| negative if and only if the total change in direction is more than $180^\circ$@>; +#ifdef DEBUGENVELOPE +dbg_nl; +dbg_key(mp_get_turn_amt_dxin_dyin);dbg_open_t;dbg_str(--[==[call mp_get_turn_amt]==]);dbg_nl; ; +dbg_n(w->x_coord);dbg_n(w->y_coord);dbg_n(dxin);dbg_n(dyin);dbg_in((d_sign > 0)); +#endif turn_amt = mp_get_turn_amt (mp, w, dxin, dyin, (d_sign > 0)); +#ifdef DEBUGENVELOPE +dbg_dn(turn_amt); +dbg_close_t;dbg_nl;dbg_nl; +#endif if (number_negative(ss)) turn_amt = turn_amt - d_sign * n @@ -14024,13 +14374,18 @@ then swapped with |(x2,y2)|. We make use of the identities new_fraction (r2); take_fraction (r1, x0, y2); take_fraction (r2, x2, y0); +#ifdef DEBUGENVELOPE +dbg_sp; +dbg_open_t;dbg_dn(d_sign);dbg_close_t;dbg_comma;dbg_nl; +#endif number_half (r1); number_half (r2); set_number_from_substraction(t0, r1, r2); set_number_from_addition (arg1, y0, y2); take_fraction (r1, x1, arg1); set_number_from_addition (arg1, x0, x2); - take_fraction (r1, y1, arg1); + /*%take_fraction (r1, y1, arg1);*//* The old one, is it correct ?*/ + take_fraction (r2, y1, arg1); number_half (r1); number_half (r2); set_number_from_substraction(t1, r1, r2); @@ -14065,6 +14420,7 @@ if (number_positive(t0)) { } { mp_number tmp1, tmp2, r1, r2, arg1; + mp_number abs_ss, eps_ss; new_fraction (r1); new_fraction (r2); new_number(arg1); @@ -14077,6 +14433,28 @@ if (number_positive(t0)) { set_number_from_addition(arg1, y0, y2); take_fraction (r2, arg1, tmp2); set_number_from_addition (ss, r1, r2); + /* BEGIN PATCH */ +#ifdef DEBUGENVELOPE +dbg_key(patch ss before);dbg_open_t;dbg_nl; +dbg_n(ss); +dbg_close_t;dbg_comma;dbg_nl; +#endif + new_number(abs_ss); + new_number(eps_ss); + set_number_from_double(eps_ss,1e-6); + number_clone(abs_ss,ss); + number_abs(abs_ss); + if (number_greaterequal(eps_ss,abs_ss)) { + set_number_to_zero(ss);/* a warning here ? */ + } +#ifdef DEBUGENVELOPE +dbg_key(patch ss after);dbg_open_t;dbg_nl; +dbg_n(ss); +dbg_close_t;dbg_comma;dbg_nl; +#endif + free_number(abs_ss); + free_number(eps_ss); + /* END PATCH */ free_number (arg1); free_number (r1); free_number (r2); @@ -15915,8 +16293,8 @@ static mp_value_node mp_p_plus_fq (MP mp, mp_value_node p, mp_number f, } else { if (number_greaterequal (absv, coef_bound_k) && mp->watch_coefs) { mp_type (qq) = independent_needing_fix; - /* If we set this , then we can drop (mp_type(pp) == independent_needing_fix && mp->fix_needed) later */ - /* set_number_from_scaled (value_number (qq), indep_value(qq)); */ + /* If we set this , then we can drop |(mp_type(pp) == independent_needing_fix && mp->fix_needed)| later */ + /* |set_number_from_scaled (value_number (qq), indep_value(qq));| */ mp->fix_needed = true; } set_mp_link (r, (mp_node) s); @@ -16060,8 +16438,8 @@ static mp_value_node mp_p_plus_q (MP mp, mp_value_node p, mp_value_node q, } else { if (number_greaterequal(test, coef_bound_k) && mp->watch_coefs) { mp_type (qq) = independent_needing_fix; - /* If we set this , then we can drop (mp_type(pp) == independent_needing_fix && mp->fix_needed) later */ - /* set_number_from_scaled (value_number (qq), indep_value(qq)); */ + /* If we set this , then we can drop |(mp_type(pp) == independent_needing_fix && mp->fix_needed)| later */ + /* |set_number_from_scaled (value_number (qq), indep_value(qq));| */ mp->fix_needed = true; } set_mp_link (r, (mp_node) s); @@ -24675,7 +25053,7 @@ static void mp_do_nullary (MP mp, quarterword c) { { mp_number r; new_number (r); - /*mp_norm_rand (mp, &r);*/ + /*|mp_norm_rand (mp, &r)|;*/ m_norm_rand (r); mp->cur_exp.type = mp_known; set_cur_exp_value_number (r); @@ -24872,7 +25250,7 @@ static void mp_do_unary (MP mp, quarterword c) { { mp_number vvx; new_number (vvx); - /*mp_unif_rand (mp, &vvx, cur_exp_value_number ());*/ + /*|mp_unif_rand (mp, &vvx, cur_exp_value_number ());|*/ m_unif_rand (vvx, cur_exp_value_number ()); set_cur_exp_value_number (vvx); free_number (vvx); diff --git a/Build/source/texk/web2c/mplibdir/mpmathbinary.w b/Build/source/texk/web2c/mplibdir/mpmathbinary.w index f0d134a58e1..287243c6d26 100644 --- a/Build/source/texk/web2c/mplibdir/mpmathbinary.w +++ b/Build/source/texk/web2c/mplibdir/mpmathbinary.w @@ -1100,6 +1100,24 @@ void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_ mpfr_set(b, (mpfr_ptr )b_orig.data.num, ROUNDING); mpfr_set(c, (mpfr_ptr )c_orig.data.num, ROUNDING); mpfr_set(d, (mpfr_ptr )d_orig.data.num, ROUNDING); + + mpfr_mul(q,a,b,ROUNDING); + mpfr_mul(r,c,d,ROUNDING); + cmp = mpfr_cmp(q,r); + if (cmp==0) { + mpfr_set(ret->data.num, zero, ROUNDING); + goto RETURN; + } + if (cmp>0) { + mpfr_set(ret->data.num, one, ROUNDING); + goto RETURN; + } + if (cmp<0) { + mpfr_set(ret->data.num, minusone, ROUNDING); + goto RETURN; + } + + /*TODO: remove this part of the code until RETURN */ @<Reduce to the case that |a,c>=0|, |b,d>0|@>; while (1) { mpfr_div(q,a,d, ROUNDING); diff --git a/Build/source/texk/web2c/mplibdir/mpmathdecimal.w b/Build/source/texk/web2c/mplibdir/mpmathdecimal.w index d0550c51a80..6394372c5c7 100644 --- a/Build/source/texk/web2c/mplibdir/mpmathdecimal.w +++ b/Build/source/texk/web2c/mplibdir/mpmathdecimal.w @@ -1213,11 +1213,21 @@ The result is $+1$, 0, or~$-1$ in the three respective cases. void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_number c_orig, mp_number d_orig) { decNumber q, r, test; /* temporary registers */ decNumber a, b, c, d; + decNumber ab, cd; (void)mp; decNumberCopy(&a, (decNumber *)a_orig.data.num); decNumberCopy(&b, (decNumber *)b_orig.data.num); decNumberCopy(&c, (decNumber *)c_orig.data.num); decNumberCopy(&d, (decNumber *)d_orig.data.num); + + decNumberMultiply (&ab, (decNumber *)a_orig.data.num, (decNumber *)b_orig.data.num, &set); + decNumberMultiply (&cd, (decNumber *)c_orig.data.num, (decNumber *)d_orig.data.num, &set); + decNumberCompare(ret->data.num, &ab, &cd, &set); + mp_check_decNumber(mp, ret->data.num, &set); + if (1>0) + return; + + @<Reduce to the case that |a,c>=0|, |b,d>0|@>; while (1) { decNumberDivide(&q,&a,&d, &set); @@ -1699,13 +1709,13 @@ static void sinecosine(decNumber *theangle, decNumber *c, decNumber *s) @c void mp_decimal_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n_sin) { decNumber rad; + double tmp; decNumber one_eighty; - decNumberFromInt32(&one_eighty, 180 * 16); + tmp = mp_number_to_double(z_orig)/16.0; + #if DEBUG fprintf(stdout, "\nsin_cos(%f)", mp_number_to_double(z_orig)); #endif - decNumberMultiply(&rad, z_orig.data.num, &PI_decNumber, &set); - decNumberDivide(&rad, &rad, &one_eighty, &set); #if 0 if (decNumberIsNegative(&rad)) { while (decNumberLess(&rad,&PI_decNumber)) @@ -1715,9 +1725,23 @@ void mp_decimal_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n decNumberSubtract(&rad, &rad, &PI_decNumber, &set); } #endif - sinecosine(&rad, n_sin->data.num, n_cos->data.num); - decNumberMultiply(n_cos->data.num,n_cos->data.num,&fraction_multiplier_decNumber, &set); - decNumberMultiply(n_sin->data.num,n_sin->data.num,&fraction_multiplier_decNumber, &set); + if ((tmp == 90.0)||(tmp == -270)){ + decNumberZero(n_cos->data.num); + decNumberCopy(n_sin->data.num,&fraction_multiplier_decNumber); + } else if ((tmp == -90.0)||(tmp == 270.0)) { + decNumberZero(n_cos->data.num); + decNumberCopyNegate(n_sin->data.num,&fraction_multiplier_decNumber); + } else if ((tmp == 180.0) || (tmp == -180.0)) { + decNumberCopyNegate(n_cos->data.num,&fraction_multiplier_decNumber); + decNumberZero(n_sin->data.num); + } else { + decNumberFromInt32(&one_eighty, 180 * 16); + decNumberMultiply(&rad, z_orig.data.num, &PI_decNumber, &set); + decNumberDivide(&rad, &rad, &one_eighty, &set); + sinecosine(&rad, n_sin->data.num, n_cos->data.num); + decNumberMultiply(n_cos->data.num,n_cos->data.num,&fraction_multiplier_decNumber, &set); + decNumberMultiply(n_sin->data.num,n_sin->data.num,&fraction_multiplier_decNumber, &set); + } #if DEBUG fprintf(stdout, "\nsin_cos(%f,%f,%f)", decNumberToDouble(&rad), mp_number_to_double(*n_cos), mp_number_to_double(*n_sin)); diff --git a/Build/source/texk/web2c/mplibdir/mpmathdouble.w b/Build/source/texk/web2c/mplibdir/mpmathdouble.w index d5663b2df97..9caf70653b6 100644 --- a/Build/source/texk/web2c/mplibdir/mpmathdouble.w +++ b/Build/source/texk/web2c/mplibdir/mpmathdouble.w @@ -1,4 +1,4 @@ -% $Id: mpmathdouble.w 2070 2015-10-06 10:35:23Z luigi $ +% $Id: mpmathdouble.w 2091 2016-09-16 23:07:58Z luigi $ % % This file is part of MetaPost; % the MetaPost program is in the public domain. @@ -814,6 +814,11 @@ void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_ integer q, r; /* temporary registers */ integer a, b, c, d; (void)mp; + + mp_double_ab_vs_cd(mp,ret, a_orig, b_orig, c_orig, d_orig); + if (1>0) + return ; + /* TODO: remove this code until the end */ a = a_orig.data.dval; b = b_orig.data.dval; c = c_orig.data.dval; @@ -1208,9 +1213,21 @@ any loss of accuracy. Then |x| and~|y| are divided by~|r|. @c void mp_double_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n_sin) { double rad; - rad = (z_orig.data.dval / angle_multiplier) * PI/180.0; - n_cos->data.dval = cos(rad) * fraction_multiplier; - n_sin->data.dval = sin(rad) * fraction_multiplier; + rad = (z_orig.data.dval / angle_multiplier); /* still degrees */ + if ((rad == 90.0)||(rad == -270)){ + n_cos->data.dval = 0.0; + n_sin->data.dval = fraction_multiplier; + } else if ((rad == -90.0)||(rad == 270.0)) { + n_cos->data.dval = 0.0; + n_sin->data.dval = -fraction_multiplier; + } else if ((rad == 180.0) || (rad == -180.0)) { + n_cos->data.dval = -fraction_multiplier; + n_sin->data.dval = 0.0; + } else { + rad = rad * PI/180.0; + n_cos->data.dval = cos(rad) * fraction_multiplier; + n_sin->data.dval = sin(rad) * fraction_multiplier; + } #if DEBUG fprintf(stdout, "\nsin_cos(%f,%f,%f)", mp_number_to_double(z_orig), mp_number_to_double(*n_cos), mp_number_to_double(*n_sin)); |