2026-09-07 20:59:58 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| Int.mqh |
|
| | | | //| Copyright 2026, Niquel Mendoza. |
|
| | | | //| https://www.mql5.com |
|
| | | | //+------------------------------------------------------------------+
|
| | | | #property copyright "Copyright 2026, Niquel Mendoza."
|
| | | | #property link "https://www.mql5.com"
|
| | | | #property strict
|
| | | |
|
2026-09-07 21:55:02 -05:00 | | | | #ifndef BIGNUMBERSBYLEO_SRC_INT_MQH
|
| | | | #define BIGNUMBERSBYLEO_SRC_INT_MQH
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
| | | | #include "Uint.mqh"
|
2026-09-07 20:59:58 -05:00 | | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
| | | | namespace TSN
|
| | | | {
|
| | | | //+------------------------------------------------------------------+
|
2026-09-07 21:55:02 -05:00 | | | | //| Clase big integer |
|
2026-09-07 20:59:58 -05:00 | | | | //+------------------------------------------------------------------+
|
2026-09-09 20:01:20 -05:00 | | | | struct BigInteger : public BigIBase
|
2026-09-07 20:59:58 -05:00 | | | | {
|
2026-09-08 12:22:29 -05:00 | | | | private:
|
| | | | void SubInPlaceMayorQue(const ulong& v[], const int bsize_abs);
|
2026-09-08 17:43:42 -05:00 | | | | void SumInPlace(const ulong &v[], const int bsize_abs);
|
2026-09-08 12:22:29 -05:00 | | | |
|
| | | | public:
|
2026-09-07 21:55:02 -05:00 | | | | //---
|
| | | | BigInteger(ulong& v[], const int vs_8);
|
2026-09-10 08:11:32 -05:00 | | | | BigInteger(int initial_reserve);
|
2026-09-07 21:55:02 -05:00 | | | | BigInteger();
|
| | | |
|
2026-09-07 20:59:58 -05:00 | | | |
|
| | | | //---
|
2026-09-11 12:15:57 -05:00 | | | | __forceinline int Cmp(const BigIBase& b) const { return CmpInt<BigInteger>(b); }
|
| | | | int CmpAbs(const BigInteger& b) const;
|
| | | |
|
| | | | //---
|
| | | | __forceinline void Neg() { m_v_s = -m_v_s; }
|
2026-09-07 21:55:02 -05:00 | | | | void operator+=(const BigInteger& b);
|
| | | | void operator-=(const BigInteger& b);
|
2026-09-07 20:59:58 -05:00 | | | | void operator>>=(const ulong b);
|
| | | |
|
2026-09-08 21:37:36 -05:00 | | | | //--- floor
|
2026-09-11 12:15:57 -05:00 | | | | // Esta funcion aplica un florr (div y this es el reto osea)
|
| | | | // this = this % b
|
| | | | void ModFloor(BigUInteger& b);
|
2026-09-08 12:22:29 -05:00 | | | |
|
2026-09-07 21:55:02 -05:00 | | | | //---
|
| | | | // GDC extenndio para retonar x:
|
| | | | // si tenemos:
|
| | | | // ax+by=gdc(a,b)
|
| | | | // osea:
|
| | | | // this*x+b*y=gdc(this,b)
|
| | | | // Esta funcion retorna el (x)
|
| | | | // Tambien se peude ver como si se tratase de obtener el inveosr modular de this, donde b es el mod
|
| | | | // this * x = 1 (mod b)
|
| | | | static BigInteger GdcExtendedRetX(const BigUInteger& a, const BigUInteger& b);
|
| | | |
|
| | | | //---
|
2026-09-11 12:15:57 -05:00 | | | | static __forceinline int AbsS(int v) { return v >= 0 ? v : -v;}
|
2026-09-07 20:59:58 -05:00 | | | | };
|
| | | |
|
2026-09-07 21:55:02 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-10 08:11:32 -05:00 | | | | BigInteger::BigInteger(ulong& v[], const int vs_8)
|
| | | | : BigIBase(v, vs_8)
|
2026-09-07 21:55:02 -05:00 | | | | {
|
| | | | }
|
| | | |
|
2026-09-10 08:11:32 -05:00 | | | |
|
2026-09-07 21:55:02 -05:00 | | | | //+------------------------------------------------------------------+
|
2026-09-10 08:11:32 -05:00 | | | | BigInteger::BigInteger(int initial_reserve)
|
| | | | : BigIBase(initial_reserve)
|
2026-09-07 21:55:02 -05:00 | | | | {
|
| | | | }
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-10 08:11:32 -05:00 | | | | BigInteger::BigInteger(void)
|
| | | | : BigIBase()
|
2026-09-07 21:55:02 -05:00 | | | | {
|
2026-09-08 17:43:42 -05:00 | | | | }
|
| | | |
|
2026-09-10 08:11:32 -05:00 | | | |
|
2026-09-11 12:15:57 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
| | | | int BigInteger::CmpAbs(const BigInteger &b) const
|
| | | | {
|
| | | | // iniciales
|
| | | | const int abs_this_s = BIGNUMERBYLEO_ABS(m_v_s);
|
| | | | const int abs_other_s = BIGNUMERBYLEO_ABS(b.m_v_s);
|
| | | | if(abs_this_s > abs_other_s)
|
| | | | return BIGINTEGER_CMP_MAYOR;
|
| | | | if(abs_this_s < abs_other_s)
|
| | | | return BIGINTEGER_CMP_MENOR;
|
| | | | // equal en size
|
| | | | for(int i = abs_this_s - 1; i >= 0; i--)
|
| | | | {
|
| | | | if(m_v[i] != b.m_v[i]) // no coindice
|
| | | | return m_v[i] > b.m_v[i] ? BIGINTEGER_CMP_MAYOR : BIGINTEGER_CMP_MENOR;
|
| | | | }
|
| | | | return BIGINTEGER_CMP_EQ; // iguales
|
| | | | }
|
| | | |
|
2026-09-07 21:55:02 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-08 12:22:29 -05:00 | | | | void BigInteger::SumInPlace(const ulong &v[], const int bsize_abs)
|
2026-09-07 21:55:02 -05:00 | | | | {
|
2026-09-08 12:22:29 -05:00 | | | | // mismo signo
|
| | | | // añadir normal
|
| | | | //---
|
2026-09-10 09:23:17 -05:00 | | | | BIGNUMERBYLEO_INT_NORMALIZE(m_v_s)
|
2026-09-08 12:22:29 -05:00 | | | | const int lkc = m_v_s;
|
| | | |
|
| | | | //---
|
| | | | ulong carry = 0;
|
| | | | int i = 0;
|
| | | |
|
| | | | //---
|
| | | | if(m_v_s > bsize_abs) // this mayor
|
2026-09-07 22:14:03 -05:00 | | | | {
|
2026-09-08 12:22:29 -05:00 | | | | m_v_s++; // por si el carry
|
| | | | if(m_v_s > ArraySize(m_v))
|
| | | | ArrayResize(m_v, m_v_s, m_v_s);
|
2026-09-07 22:14:03 -05:00 | | | |
|
2026-09-08 12:22:29 -05:00 | | | | //-- empezamos por b que es el menor
|
| | | | for(; i < bsize_abs; i++)
|
| | | | {
|
2026-09-08 17:43:42 -05:00 | | | | const ulong s1 = (m_v[i] += v[i]); // suma 1
|
2026-09-08 12:22:29 -05:00 | | | | const ulong r = (m_v[i] += carry); // suma 2
|
2026-09-08 17:43:42 -05:00 | | | | carry = (s1 < v[i]) | (r < s1); // carry base, luego carray de al suma previa
|
2026-09-08 12:22:29 -05:00 | | | | }
|
| | | | // propagamos el carry
|
| | | | for(; i < lkc; i++)
|
| | | | {
|
| | | | const ulong r = (m_v[i] += carry);
|
| | | | carry = (r < carry);
|
| | | | }
|
| | | | }
|
| | | | else // el otro mayor
|
| | | | {
|
| | | | m_v_s = bsize_abs + 1; // mayor
|
| | | | if(m_v_s > ArraySize(m_v))
|
| | | | ArrayResize(m_v, m_v_s, m_v_s);
|
2026-09-07 22:14:03 -05:00 | | | |
|
2026-09-08 12:22:29 -05:00 | | | | //--- comun
|
| | | | for(; i < lkc; i++)
|
| | | | {
|
2026-09-08 17:43:42 -05:00 | | | | const ulong s1 = (m_v[i] += v[i]); // suma 1
|
2026-09-08 12:22:29 -05:00 | | | | const ulong r = (m_v[i] += carry); // suma 2
|
2026-09-08 17:43:42 -05:00 | | | | carry = (s1 < v[i]) | (r < s1); // carry base, luego carray de al suma previa
|
2026-09-08 12:22:29 -05:00 | | | | }
|
| | | | // carry
|
| | | | for(; i < bsize_abs; i++)
|
| | | | {
|
2026-09-08 17:43:42 -05:00 | | | | const ulong r = v[i] + carry;
|
2026-09-08 12:22:29 -05:00 | | | | m_v[i] = r;
|
2026-09-08 17:43:42 -05:00 | | | | carry = (r < v[i]);
|
2026-09-08 12:22:29 -05:00 | | | | }
|
2026-09-07 22:14:03 -05:00 | | | | }
|
2026-09-08 12:22:29 -05:00 | | | |
|
| | | | //---
|
| | | | if(carry)
|
| | | | m_v[i] = 1;
|
2026-09-07 22:14:03 -05:00 | | | | else
|
2026-09-08 12:22:29 -05:00 | | | | m_v_s--; // no hay carry exacto
|
2026-09-10 09:23:17 -05:00 | | | |
|
| | | | //---
|
| | | | BIGNUMERBYLEO_INT_SNEG(m_v_s)
|
2026-09-08 12:22:29 -05:00 | | | | }
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-08 17:43:42 -05:00 | | | | void BigInteger::SubInPlaceMayorQue(const ulong &v[], const int vs)
|
2026-09-08 12:22:29 -05:00 | | | | {
|
2026-09-08 17:43:42 -05:00 | | | | //----
|
2026-09-10 09:23:17 -05:00 | | | | BIGNUMERBYLEO_INT_NORMALIZE(m_v_s)
|
2026-09-08 17:43:42 -05:00 | | | | ulong borrow = 0;
|
| | | | int i = 0;
|
2026-09-08 12:22:29 -05:00 | | | |
|
2026-09-08 17:43:42 -05:00 | | | | //---
|
| | | | // Chekea ambos daod qeu b en caso pueda tener mas bytes esos ya no se procesan
|
| | | | for(; i < vs; i++)
|
| | | | {
|
| | | | const ulong res_bor = m_v[i] - borrow; // paso 0 (a-resto)
|
| | | | const ulong res_f = res_bor - v[i]; // paso 1 (r-b)
|
| | | | borrow = (m_v[i] < borrow) | // en caso sea menor (tipo m_v es 0 y borro viene cno 1
|
| | | | // en ese caso tendremismo qeu prestarmos 1..
|
| | | | // Igual aqui si el left menor al right tendra uqe prestartse
|
| | | | (res_bor < v[i]);
|
| | | | //Print(res_f);
|
| | | | m_v[i] = res_f;
|
| | | | }
|
| | | | // sobra
|
| | | | for(; i < m_v_s; i++)
|
| | | | {
|
| | | | const ulong r = m_v[i] - borrow;
|
| | | | borrow = (m_v[i] < borrow); // si es menor enonces hubo uover
|
| | | | m_v[i] = r;
|
| | | | }
|
2026-09-08 12:22:29 -05:00 | | | |
|
2026-09-08 17:43:42 -05:00 | | | | //---
|
2026-09-10 08:11:32 -05:00 | | | | BIGNUMBERSBYLEO_CLEAN_HIGH_ZEROS(m_v, m_v_s)
|
2026-09-10 09:23:17 -05:00 | | | | BIGNUMERBYLEO_INT_SNEG(m_v_s)
|
2026-09-08 12:22:29 -05:00 | | | | }
|
| | | |
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
| | | | void BigInteger::operator+=(const BigInteger& b)
|
| | | | {
|
| | | | //---
|
2026-09-10 09:23:17 -05:00 | | | | // En caos sea 0 entonces podira ir a la rama de sumimplace solo si b tambien es positivo
|
| | | | // ahora en caso sea difenite va a la rama de cmp menor .. en ese caos se resitarai this = x-this
|
| | | | // y como x puede digmoa ser 0 no daria ningun error...
|
2026-09-08 12:22:29 -05:00 | | | | const int bsize = b.m_v_s;
|
| | | | //--- chekeamos signo
|
| | | | if((m_v_s ^ bsize) < 0) // diferente
|
| | | | {
|
2026-09-11 12:15:57 -05:00 | | | | switch(CmpAbs(b))
|
2026-09-08 12:22:29 -05:00 | | | | {
|
| | | | case BIGINTEGER_CMP_EQ:
|
| | | | {
|
2026-09-10 09:23:17 -05:00 | | | | BIGNUMBERBYLEO_ZERO
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | case BIGINTEGER_CMP_MAYOR:
|
| | | | {
|
2026-09-09 20:01:20 -05:00 | | | | SubInPlaceMayorQue(b.m_v, BIGNUMERBYLEO_ABS(bsize));
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | case BIGINTEGER_CMP_MENOR:
|
| | | | {
|
2026-09-11 12:15:57 -05:00 | | | | m_v_s = BIGNUMERBYLEO_ABS(m_v_s);
|
2026-09-10 12:25:44 -05:00 | | | | b.RestarConYResEn(m_v, m_v_s);
|
2026-09-11 12:15:57 -05:00 | | | | if(b.m_v_s < 0)
|
| | | | m_v_s = -m_v_s;
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | default:
|
| | | | break;
|
| | | | }
|
| | | | }
|
| | | | else // signos iguales
|
| | | | {
|
| | | | //--- si es negativo lo cambiamos
|
2026-09-09 20:01:20 -05:00 | | | | SumInPlace(b.m_v, BIGNUMERBYLEO_ABS(bsize));
|
2026-09-08 12:22:29 -05:00 | | | | }
|
| | | | }
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-08 17:43:42 -05:00 | | | | /* Usamos mismo alg que sum pero con - esto es posuible
|
| | | | dado qeu tenemos que:
|
| | | | 1) a - b = a + (-b)
|
| | | | 2) -a - b = (-a) + (-b)
|
| | | | 3) a - (-b) = a + b ; nota que (-(-b) = b)
|
| | | | 4) -a - -b = (-a) + (b) (justo lo mismo)
|
| | | |
|
| | | | Osea negando el signo del b podemos replicar con una "suma" lo que haiamos con la resta
|
| | | | */
|
2026-09-08 12:22:29 -05:00 | | | | void BigInteger::operator-=(const BigInteger& b)
|
| | | | {
|
| | | | //---
|
| | | | const int bsize = -b.m_v_s;
|
| | | | //--- chekeamos signo
|
| | | | if((m_v_s ^ bsize) < 0) // diferente
|
| | | | {
|
2026-09-11 14:45:51 -05:00 | | | | switch(CmpAbs(b))
|
2026-09-08 12:22:29 -05:00 | | | | {
|
| | | | case BIGINTEGER_CMP_EQ:
|
| | | | {
|
2026-09-10 09:23:17 -05:00 | | | | BIGNUMBERBYLEO_ZERO
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | case BIGINTEGER_CMP_MAYOR:
|
| | | | {
|
2026-09-09 20:01:20 -05:00 | | | | SubInPlaceMayorQue(b.m_v, BIGNUMERBYLEO_ABS(bsize));
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | case BIGINTEGER_CMP_MENOR:
|
| | | | {
|
2026-09-11 12:15:57 -05:00 | | | | m_v_s = BIGNUMERBYLEO_ABS(m_v_s);
|
2026-09-10 12:25:44 -05:00 | | | | b.RestarConYResEn(m_v, m_v_s);
|
2026-09-11 12:15:57 -05:00 | | | | if(b.m_v_s < 0)
|
| | | | m_v_s = -m_v_s;
|
2026-09-08 12:22:29 -05:00 | | | | break;
|
| | | | }
|
| | | | default:
|
| | | | break;
|
| | | | }
|
| | | | }
|
| | | | else // signos iguales
|
| | | | {
|
| | | | //--- si es negativo lo cambiamos
|
2026-09-09 20:01:20 -05:00 | | | | SumInPlace(b.m_v, BIGNUMERBYLEO_ABS(bsize));
|
2026-09-07 22:14:03 -05:00 | | | | }
|
2026-09-07 21:55:02 -05:00 | | | | }
|
| | | |
|
| | | |
|
2026-09-08 17:43:42 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
| | | | void BigInteger::operator>>=(const ulong b)
|
| | | | {
|
| | | |
|
| | | |
|
| | | | }
|
| | | |
|
| | | |
|
| | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-08 21:37:36 -05:00 | | | | // =
|
| | | | // q = floor(this/b)
|
2026-09-09 12:01:07 -05:00 | | | | // retorna R
|
2026-09-11 12:15:57 -05:00 | | | | void BigInteger::ModFloor(BigUInteger& b)
|
2026-09-08 17:43:42 -05:00 | | | | {
|
2026-09-08 21:37:36 -05:00 | | | | //---
|
| | | | const int bs = b.m_v_s;
|
| | | | const int sing = m_v_s ^ bs;
|
2026-09-09 20:01:20 -05:00 | | | | const int s = BIGNUMERBYLEO_ABS(m_v_s);
|
2026-09-08 17:43:42 -05:00 | | | |
|
2026-09-08 21:37:36 -05:00 | | | | //---
|
2026-09-09 12:01:07 -05:00 | | | | if(s < bs) // menor
|
2026-09-08 21:37:36 -05:00 | | | | {
|
2026-09-11 12:15:57 -05:00 | | | | if(sing < 0) // diiferen (- y +)
|
2026-09-08 21:37:36 -05:00 | | | | {
|
| | | | // r = n (this) + d (B)
|
2026-09-11 12:15:57 -05:00 | | | | // aparte como b es mayor dicho signo manda..
|
| | | | // this = (b) - |(this)| da positivo siempre asi que
|
| | | | m_v_s = s;
|
| | | | b.RestarConYResEn(m_v, m_v_s);
|
2026-09-08 21:37:36 -05:00 | | | | }
|
2026-09-11 12:15:57 -05:00 | | | | // es + entonces tal cual x % y el resto es x.. si es menor (Como en este caso)
|
2026-09-08 21:37:36 -05:00 | | | | }
|
| | | | else // this mayor o igual
|
| | | | {
|
2026-09-09 12:01:07 -05:00 | | | | BigUInteger temp(m_v, s);
|
| | | | temp %= b; // reduce aqui mismo
|
2026-09-08 17:43:42 -05:00 | | | |
|
2026-09-10 12:25:44 -05:00 | | | | //--- intercambiamos
|
| | | | ArraySwap(m_v, temp.m_v);
|
2026-09-11 12:15:57 -05:00 | | | | m_v_s = temp.m_v_s; // (ojo ya es positiuvio..)
|
2026-09-09 12:01:07 -05:00 | | | |
|
| | | | //---
|
2026-09-10 12:25:44 -05:00 | | | | if(sing < 0) // this es - lo que quiere decir que es menor a b (Aunque siempre lo sera ahora mismo por el %)
|
2026-09-09 12:01:07 -05:00 | | | | {
|
2026-09-10 10:15:26 -05:00 | | | | // ahota mismo this es menor que b (divisor)
|
| | | | // la idea es que como el resto ahora es negativo
|
| | | | // le sumasmos el diivosr -this += b
|
| | | | // en ese caso seria como hace b - this
|
| | | | // con signo del mayor (+) como final (signo final)
|
| | | |
|
2026-09-10 12:25:44 -05:00 | | | | //m_v_s = -m_v_s; NO dado qeu usamos el positivo
|
| | | | // this = b - this (magnitudes)
|
| | | | b.RestarConYResEn(m_v, m_v_s);
|
| | | | // ahor amismo this ya es positivo
|
2026-09-09 12:01:07 -05:00 | | | | }
|
2026-09-08 21:37:36 -05:00 | | | | }
|
2026-09-08 17:43:42 -05:00 | | | | }
|
2026-09-08 12:22:29 -05:00 | | | |
|
2026-09-07 21:55:02 -05:00 | | | | //+------------------------------------------------------------------+
|
| | | | //| |
|
| | | | //+------------------------------------------------------------------+
|
2026-09-11 12:15:57 -05:00 | | | | // Obtiene el GDC EXT (el coeficiente x de benzout % mod positivo en un div floor)
|
| | | | BigUInteger BNBL_GdcExtendedRetXWMod(const BigUInteger& a, const BigUInteger& b, const BigUInteger& mod)
|
2026-09-07 21:55:02 -05:00 | | | | {
|
| | | | //--
|
2026-09-11 12:15:57 -05:00 | | | | const ulong gz = BigUInteger::CTZ_Commons(a, b); // 2 commons
|
2026-09-07 21:55:02 -05:00 | | | | //--- quitamos 2 commons (ahora son impares)
|
2026-09-10 07:16:18 -05:00 | | | | // u = a * 2^p
|
| | | | // v = b * 2^p
|
| | | | // quita los 2^p
|
2026-09-11 12:15:57 -05:00 | | | | BigUInteger u = a >> gz;
|
| | | | BigUInteger v = b >> gz;
|
2026-09-09 20:01:20 -05:00 | | | |
|
| | | | // lo que queda (0) en caso de que ya sea impar >= 1
|
| | | | // en caso de que no sea impar
|
| | | | ulong uz = u.Ctz(); // restante
|
| | | | ulong vz = v.Ctz(); // restante
|
| | | |
|
| | | | //----
|
| | | | /*
|
| | | | Invariante base la idea es u\v originales aparteis de los "curr"
|
2026-09-11 09:36:42 -05:00 | | | | u= t0*tu + t1tv
|
| | | | v= s0*tu + s1tv
|
2026-09-09 20:01:20 -05:00 | | | |
|
| | | | Algo difernte del gdc ext bin tradicional es como la inversa
|
| | | | la idea luego con esto es que "invertimos" por lo que en el looop caliente en vez de dividir
|
| | | | podemos mul lo que no perjudica paridad, pro loq eu no hace falta un while de ajuiste..
|
| | | | eso solo al final..
|
| | | | */
|
2026-09-07 21:55:02 -05:00 | | | |
|
| | | | //---
|
2026-09-09 12:01:07 -05:00 | | | | const bool swap = u.m_v_s < v.m_v_s;
|
| | | | if(swap)
|
2026-09-09 20:01:20 -05:00 | | | | {
|
2026-09-09 12:01:07 -05:00 | | | | u.Swap(v);
|
2026-09-09 20:01:20 -05:00 | | | | BIGNUMERBYLEO_SWAP(uz, vz, ulong)
|
| | | | }
|
| | | |
|
| | | |
|
2026-09-10 07:16:18 -05:00 | | | | //--- ahora iniciamos los valores de los coeficintes
|
| | | | // como ay hemos modificado varios valores entonces tendremos que reflejar esos cambios
|
| | | | //--- s1
|
2026-09-09 20:01:20 -05:00 | | | | // v con todos los cambios es ahora mismo
|
| | | | // v = 2^vz * tv
|
| | | | // v=s0⋅tu+s1⋅tv
|
| | | | // s0=0
|
| | | | // v = s1tv
|
| | | | // s1 = 2^vz
|
2026-09-10 07:16:18 -05:00 | | | | const int limbs_s = int((vz >> 6) + 1);
|
2026-09-10 09:23:17 -05:00 | | | | BigInteger s1(limbs_s); // reservamos con
|
2026-09-10 13:29:20 -05:00 | | | | ArrayInitialize(s1.m_v, 0ULL); // iniciamos a 0 todo el arr
|
2026-09-10 07:16:18 -05:00 | | | | s1.SetBit(vz, true);
|
| | | | // s0 como detemrinamos sera 0
|
2026-09-10 09:23:17 -05:00 | | | | BigInteger s0(limbs_s);
|
2026-09-10 07:16:18 -05:00 | | | |
|
| | | |
|
| | | | //--- ahora t
|
2026-09-11 09:36:42 -05:00 | | | | // u=
|
2026-09-10 07:16:18 -05:00 | | | | // u = 2^uz * tu_prev
|
| | | | // tu_prev = q * tv + tu_actual
|
| | | | // u = 2^uz * (q * tv + tu_actual)
|
| | | | // u = (2^uz * q * tv) + (2^uz * tu_actual)
|
| | | | // reordenando
|
| | | | // u = (2^uz * tu_actual) + (2^uz * q * tv)
|
| | | | // t0 = 2^uz
|
| | | | // t1 = 2^uz * q
|
2026-09-11 09:36:42 -05:00 | | | | u %= v; // u = u % v (resto de divisor u\v)
|
2026-09-10 07:16:18 -05:00 | | | |
|
| | | | // ahora si actulziamso t0\t1
|
| | | | //const int limbs_t = int((uz >> 6) + 1);
|
| | | | //BigInteger t0(TSN::BigIBase::EMPTY_INITIAL_RESERVE, limbs_t);
|
| | | | //t0.SetBit(uz, true);
|
2026-09-09 20:01:20 -05:00 | | | |
|
2026-09-11 12:15:57 -05:00 | | | | ulong p = uz + vz; // sob
|
| | | |
|
2026-09-09 12:01:07 -05:00 | | | | //---
|
2026-09-10 07:16:18 -05:00 | | | | if(u.IsNotZero())
|
2026-09-09 12:01:07 -05:00 | | | | {
|
2026-09-10 07:16:18 -05:00 | | | | const ulong shift = u.Ctz();
|
2026-09-10 13:29:20 -05:00 | | | | // aplicamos a u
|
| | | | u <<= shift;
|
2026-09-10 07:16:18 -05:00 | | | | // s0 le aplicamos
|
2026-09-11 14:45:51 -05:00 | | | | s0.UShiftLeft(shift);
|
2026-09-10 07:16:18 -05:00 | | | | // t0 le aplicamos
|
| | | | p += shift;
|
2026-09-07 21:55:02 -05:00 | | | |
|
2026-09-10 13:29:20 -05:00 | | | | //---
|
2026-09-11 09:36:42 -05:00 | | | | // Aqui en hot path es basimnte el mismo algoritmo del bin normal
|
| | | | // solo que ahora tenemos que sumar para compesar los coeficientes
|
2026-09-26 20:59:30 -05:00 | | | | int cmp = u.Cmp(v);
|
| | | | while(cmp != 0) // si no es igual
|
2026-09-10 07:16:18 -05:00 | | | | {
|
2026-09-10 13:29:20 -05:00 | | | | switch(cmp)
|
| | | | {
|
| | | | case BIGINTEGER_CMP_MAYOR:
|
| | | | {
|
2026-09-11 09:36:42 -05:00 | | | | // ahora como restamos tu_nuevo = tu_viejo - tv
|
| | | | // tu_nuevo = tu_viejo - tv (+tv)
|
| | | | // tu_nuevo + tv = tu_viejo == tu_viejo = tu_nuevo + tv
|
| | | | // tu_viejo = tu_nuevo + tv
|
| | | | // u = t0*tu + t1tv
|
| | | | // u = t0*(tu_nuevo + tv) + t1tv
|
| | | | // u = t0*tu_nuevo+t0*tv + t1*tv
|
| | | | // u = t0*tu_nuevo+tv(t0 + t1)
|
| | | | // u = t0*tu+tv(t0 + t1)
|
| | | | // osea
|
| | | | // t1 = t0 + t1
|
| | | | // tambien
|
| | | | // s1 = s0 + s1
|
| | | | // la idea es que como cambiamos tu tamiben se debe de matenern la invariante
|
| | | |
|
| | | | u -= v;
|
| | | | s1 += s0; // s1 = s0 + s1
|
| | | | // t no
|
| | | | // ahora los hacemos impar denuvo a u (puede que sea par con la resta)
|
| | | | const ulong s = u.Ctz();
|
2026-09-11 14:45:51 -05:00 | | | | u <<= s;
|
| | | | s0.UShiftLeft(s);
|
2026-09-11 09:36:42 -05:00 | | | |
|
| | | | //--- añadimos
|
| | | | p += s;
|
2026-09-10 13:29:20 -05:00 | | | | break;
|
| | | | }
|
| | | | case BIGINTEGER_CMP_MENOR:
|
| | | | {
|
2026-09-11 09:36:42 -05:00 | | | | // rotacion ahora u reduce a v
|
| | | | v -= u;
|
| | | | s0 += s1;
|
| | | | // ahora los hacemos impar denuvo a u (puede que sea par con la resta)
|
| | | | const ulong s = v.Ctz();
|
2026-09-11 14:45:51 -05:00 | | | | v <<= s;
|
| | | | s1.UShiftLeft(s);
|
2026-09-11 09:36:42 -05:00 | | | |
|
| | | | //--- añadimos
|
| | | | p += s;
|
2026-09-10 13:29:20 -05:00 | | | | break;
|
| | | | }
|
| | | | default:
|
| | | | break;
|
| | | | }
|
2026-09-26 20:59:30 -05:00 | | | |
|
| | | | //---
|
| | | | cmp = u.Cmp(v);
|
2026-09-10 07:16:18 -05:00 | | | | }
|
2026-09-09 12:01:07 -05:00 | | | | }
|
| | | |
|
2026-09-11 09:36:42 -05:00 | | | | //---
|
2026-09-11 12:15:57 -05:00 | | | | v <<= gz;
|
| | | | s0.Neg();
|
| | | |
|
| | | | s1 = b \ v;
|
| | | |
|
| | | | //---
|
| | | | while(p-- > 0)
|
| | | | {
|
| | | | if(s0.IsPar())
|
| | | | {
|
| | | | s0 -= s1;
|
| | | | }
|
| | | | s0 >>= 1;
|
| | | | }
|
2026-09-11 09:36:42 -05:00 | | | |
|
2026-09-11 12:15:57 -05:00 | | | | //---
|
| | | | s1 += s0;
|
| | | | if(s0.CmpAbs(s1) == BIGINTEGER_CMP_MAYOR)
|
| | | | {
|
| | | | s0.Swap(s1);
|
| | | | }
|
2026-09-11 09:36:42 -05:00 | | | |
|
2026-09-07 21:55:02 -05:00 | | | | //---
|
2026-09-11 12:15:57 -05:00 | | | | s0.ModFloor(mod);
|
| | | | return BigUInteger(s0.m_v, s0.m_v_s);
|
2026-09-07 21:55:02 -05:00 | | | | }
|
2026-09-07 20:59:58 -05:00 | | | | }
|
| | | | //+------------------------------------------------------------------+
|
2026-09-07 21:55:02 -05:00 | | | | #endif // BIGNUMBERSBYLEO_SRC_INT_MQH
|