/deveeldb-client/Deveel.Math/Logical.cs

http://deveeldb.googlecode.com/ · C# · 802 lines · 591 code · 79 blank · 132 comment · 215 complexity · 6bf369e257716fb3e88062e2e1a337b9 MD5 · raw file

  1. //
  2. // Copyright 2009 Deveel
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. using System;
  16. namespace Deveel.Math {
  17. /**
  18. * The library implements some logical operations over {@code BigInteger}. The
  19. * operations provided are listed below.
  20. * <ul type="circle">
  21. * <li>not</li>
  22. * <li>and</li>
  23. * <li>andNot</li>
  24. * <li>or</li>
  25. * <li>xor</li>
  26. * </ul>
  27. */
  28. class Logical {
  29. /** Just to denote that this class can't be instantiated. */
  30. private Logical() { }
  31. /** @see BigInteger#not() */
  32. internal static BigInteger not(BigInteger val) {
  33. if (val.sign == 0) {
  34. return BigInteger.MinusOne;
  35. }
  36. if (val.Equals(BigInteger.MinusOne)) {
  37. return BigInteger.Zero;
  38. }
  39. int[] resDigits = new int[val.numberLength + 1];
  40. int i;
  41. if (val.sign > 0) {
  42. // ~val = -val + 1
  43. if (val.digits[val.numberLength - 1] != -1) {
  44. for (i = 0; val.digits[i] == -1; i++) {
  45. ;
  46. }
  47. } else {
  48. for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
  49. ;
  50. }
  51. if (i == val.numberLength) {
  52. resDigits[i] = 1;
  53. return new BigInteger(-val.sign, i + 1, resDigits);
  54. }
  55. }
  56. // Here a carry 1 was generated
  57. } else {// (val.sign < 0)
  58. // ~val = -val - 1
  59. for (i = 0; val.digits[i] == 0; i++) {
  60. resDigits[i] = -1;
  61. }
  62. // Here a borrow -1 was generated
  63. }
  64. // Now, the carry/borrow can be absorbed
  65. resDigits[i] = val.digits[i] + val.sign;
  66. // Copying the remaining unchanged digit
  67. for (i++; i < val.numberLength; i++) {
  68. resDigits[i] = val.digits[i];
  69. }
  70. return new BigInteger(-val.sign, i, resDigits);
  71. }
  72. /** @see BigInteger#and(BigInteger) */
  73. internal static BigInteger and(BigInteger val, BigInteger that) {
  74. if (that.sign == 0 || val.sign == 0) {
  75. return BigInteger.Zero;
  76. }
  77. if (that.Equals(BigInteger.MinusOne)) {
  78. return val;
  79. }
  80. if (val.Equals(BigInteger.MinusOne)) {
  81. return that;
  82. }
  83. if (val.sign > 0) {
  84. if (that.sign > 0) {
  85. return andPositive(val, that);
  86. } else {
  87. return andDiffSigns(val, that);
  88. }
  89. } else {
  90. if (that.sign > 0) {
  91. return andDiffSigns(that, val);
  92. } else if (val.numberLength > that.numberLength) {
  93. return andNegative(val, that);
  94. } else {
  95. return andNegative(that, val);
  96. }
  97. }
  98. }
  99. /** @return sign = 1, magnitude = val.magnitude & that.magnitude*/
  100. static BigInteger andPositive(BigInteger val, BigInteger that) {
  101. // PRE: both arguments are positive
  102. int resLength = System.Math.Min(val.numberLength, that.numberLength);
  103. int i = System.Math.Max(val.FirstNonzeroDigit, that.FirstNonzeroDigit);
  104. if (i >= resLength) {
  105. return BigInteger.Zero;
  106. }
  107. int[] resDigits = new int[resLength];
  108. for (; i < resLength; i++) {
  109. resDigits[i] = val.digits[i] & that.digits[i];
  110. }
  111. BigInteger result = new BigInteger(1, resLength, resDigits);
  112. result.CutOffLeadingZeroes();
  113. return result;
  114. }
  115. /** @return sign = positive.magnitude & magnitude = -negative.magnitude */
  116. static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) {
  117. // PRE: positive is positive and negative is negative
  118. int iPos = positive.FirstNonzeroDigit;
  119. int iNeg = negative.FirstNonzeroDigit;
  120. // Look if the trailing zeros of the negative will "blank" all
  121. // the positive digits
  122. if (iNeg >= positive.numberLength) {
  123. return BigInteger.Zero;
  124. }
  125. int resLength = positive.numberLength;
  126. int[] resDigits = new int[resLength];
  127. // Must start from max(iPos, iNeg)
  128. int i = System.Math.Max(iPos, iNeg);
  129. if (i == iNeg) {
  130. resDigits[i] = -negative.digits[i] & positive.digits[i];
  131. i++;
  132. }
  133. int limit = System.Math.Min(negative.numberLength, positive.numberLength);
  134. for (; i < limit; i++) {
  135. resDigits[i] = ~negative.digits[i] & positive.digits[i];
  136. }
  137. // if the negative was shorter must copy the remaining digits
  138. // from positive
  139. if (i >= negative.numberLength) {
  140. for (; i < positive.numberLength; i++) {
  141. resDigits[i] = positive.digits[i];
  142. }
  143. } // else positive ended and must "copy" virtual 0's, do nothing then
  144. BigInteger result = new BigInteger(1, resLength, resDigits);
  145. result.CutOffLeadingZeroes();
  146. return result;
  147. }
  148. /** @return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude)*/
  149. static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
  150. // PRE: longer and shorter are negative
  151. // PRE: longer has at least as many digits as shorter
  152. int iLonger = longer.FirstNonzeroDigit;
  153. int iShorter = shorter.FirstNonzeroDigit;
  154. // Does shorter matter?
  155. if (iLonger >= shorter.numberLength) {
  156. return longer;
  157. }
  158. int resLength;
  159. int[] resDigits;
  160. int i = System.Math.Max(iShorter, iLonger);
  161. int digit;
  162. if (iShorter > iLonger) {
  163. digit = -shorter.digits[i] & ~longer.digits[i];
  164. } else if (iShorter < iLonger) {
  165. digit = ~shorter.digits[i] & -longer.digits[i];
  166. } else {
  167. digit = -shorter.digits[i] & -longer.digits[i];
  168. }
  169. if (digit == 0) {
  170. for (i++; i < shorter.numberLength && (digit = ~(longer.digits[i] | shorter.digits[i])) == 0; i++)
  171. ; // digit = ~longer.digits[i] & ~shorter.digits[i]
  172. if (digit == 0) {
  173. // shorter has only the remaining virtual sign bits
  174. for (; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++)
  175. ;
  176. if (digit == 0) {
  177. resLength = longer.numberLength + 1;
  178. resDigits = new int[resLength];
  179. resDigits[resLength - 1] = 1;
  180. return new BigInteger(-1, resLength, resDigits);
  181. }
  182. }
  183. }
  184. resLength = longer.numberLength;
  185. resDigits = new int[resLength];
  186. resDigits[i] = -digit;
  187. for (i++; i < shorter.numberLength; i++) {
  188. // resDigits[i] = ~(~longer.digits[i] & ~shorter.digits[i];)
  189. resDigits[i] = longer.digits[i] | shorter.digits[i];
  190. }
  191. // shorter has only the remaining virtual sign bits
  192. for (; i < longer.numberLength; i++) {
  193. resDigits[i] = longer.digits[i];
  194. }
  195. BigInteger result = new BigInteger(-1, resLength, resDigits);
  196. return result;
  197. }
  198. /** @see BigInteger#andNot(BigInteger) */
  199. internal static BigInteger andNot(BigInteger val, BigInteger that) {
  200. if (that.sign == 0) {
  201. return val;
  202. }
  203. if (val.sign == 0) {
  204. return BigInteger.Zero;
  205. }
  206. if (val.Equals(BigInteger.MinusOne)) {
  207. return that.Not();
  208. }
  209. if (that.Equals(BigInteger.MinusOne)) {
  210. return BigInteger.Zero;
  211. }
  212. //if val == that, return 0
  213. if (val.sign > 0) {
  214. if (that.sign > 0) {
  215. return andNotPositive(val, that);
  216. } else {
  217. return andNotPositiveNegative(val, that);
  218. }
  219. } else {
  220. if (that.sign > 0) {
  221. return andNotNegativePositive(val, that);
  222. } else {
  223. return andNotNegative(val, that);
  224. }
  225. }
  226. }
  227. /** @return sign = 1, magnitude = val.magnitude & ~that.magnitude*/
  228. static BigInteger andNotPositive(BigInteger val, BigInteger that) {
  229. // PRE: both arguments are positive
  230. int[] resDigits = new int[val.numberLength];
  231. int limit = System.Math.Min(val.numberLength, that.numberLength);
  232. int i;
  233. for (i = val.FirstNonzeroDigit; i < limit; i++) {
  234. resDigits[i] = val.digits[i] & ~that.digits[i];
  235. }
  236. for (; i < val.numberLength; i++) {
  237. resDigits[i] = val.digits[i];
  238. }
  239. BigInteger result = new BigInteger(1, val.numberLength, resDigits);
  240. result.CutOffLeadingZeroes();
  241. return result;
  242. }
  243. /** @return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude)*/
  244. static BigInteger andNotPositiveNegative(BigInteger positive, BigInteger negative) {
  245. // PRE: positive > 0 && negative < 0
  246. int iNeg = negative.FirstNonzeroDigit;
  247. int iPos = positive.FirstNonzeroDigit;
  248. if (iNeg >= positive.numberLength) {
  249. return positive;
  250. }
  251. int resLength = System.Math.Min(positive.numberLength, negative.numberLength);
  252. int[] resDigits = new int[resLength];
  253. // Always start from first non zero of positive
  254. int i = iPos;
  255. for (; i < iNeg; i++) {
  256. // resDigits[i] = positive.digits[i] & -1 (~0)
  257. resDigits[i] = positive.digits[i];
  258. }
  259. if (i == iNeg) {
  260. resDigits[i] = positive.digits[i] & (negative.digits[i] - 1);
  261. i++;
  262. }
  263. for (; i < resLength; i++) {
  264. // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]);
  265. resDigits[i] = positive.digits[i] & negative.digits[i];
  266. }
  267. BigInteger result = new BigInteger(1, resLength, resDigits);
  268. result.CutOffLeadingZeroes();
  269. return result;
  270. }
  271. /** @return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude)*/
  272. static BigInteger andNotNegativePositive(BigInteger negative, BigInteger positive) {
  273. // PRE: negative < 0 && positive > 0
  274. int resLength;
  275. int[] resDigits;
  276. int limit;
  277. int digit;
  278. int iNeg = negative.FirstNonzeroDigit;
  279. int iPos = positive.FirstNonzeroDigit;
  280. if (iNeg >= positive.numberLength) {
  281. return negative;
  282. }
  283. resLength = System.Math.Max(negative.numberLength, positive.numberLength);
  284. int i = iNeg;
  285. if (iPos > iNeg) {
  286. resDigits = new int[resLength];
  287. limit = System.Math.Min(negative.numberLength, iPos);
  288. for (; i < limit; i++) {
  289. // 1st case: resDigits [i] = -(-negative.digits[i] & (~0))
  290. // otherwise: resDigits[i] = ~(~negative.digits[i] & ~0) ;
  291. resDigits[i] = negative.digits[i];
  292. }
  293. if (i == negative.numberLength) {
  294. for (i = iPos; i < positive.numberLength; i++) {
  295. // resDigits[i] = ~(~positive.digits[i] & -1);
  296. resDigits[i] = positive.digits[i];
  297. }
  298. }
  299. } else {
  300. digit = -negative.digits[i] & ~positive.digits[i];
  301. if (digit == 0) {
  302. limit = System.Math.Min(positive.numberLength, negative.numberLength);
  303. for (i++; i < limit && (digit = ~(negative.digits[i] | positive.digits[i])) == 0; i++)
  304. ; // digit = ~negative.digits[i] & ~positive.digits[i]
  305. if (digit == 0) {
  306. // the shorter has only the remaining virtual sign bits
  307. for (; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
  308. ; // digit = -1 & ~positive.digits[i]
  309. for (; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
  310. ; // digit = ~negative.digits[i] & ~0
  311. if (digit == 0) {
  312. resLength++;
  313. resDigits = new int[resLength];
  314. resDigits[resLength - 1] = 1;
  315. return new BigInteger(-1, resLength, resDigits);
  316. }
  317. }
  318. }
  319. resDigits = new int[resLength];
  320. resDigits[i] = -digit;
  321. i++;
  322. }
  323. limit = System.Math.Min(positive.numberLength, negative.numberLength);
  324. for (; i < limit; i++) {
  325. //resDigits[i] = ~(~negative.digits[i] & ~positive.digits[i]);
  326. resDigits[i] = negative.digits[i] | positive.digits[i];
  327. }
  328. // Actually one of the next two cycles will be executed
  329. for (; i < negative.numberLength; i++) {
  330. resDigits[i] = negative.digits[i];
  331. }
  332. for (; i < positive.numberLength; i++) {
  333. resDigits[i] = positive.digits[i];
  334. }
  335. BigInteger result = new BigInteger(-1, resLength, resDigits);
  336. return result;
  337. }
  338. /** @return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude)*/
  339. static BigInteger andNotNegative(BigInteger val, BigInteger that) {
  340. // PRE: val < 0 && that < 0
  341. int iVal = val.FirstNonzeroDigit;
  342. int iThat = that.FirstNonzeroDigit;
  343. if (iVal >= that.numberLength) {
  344. return BigInteger.Zero;
  345. }
  346. int resLength = that.numberLength;
  347. int[] resDigits = new int[resLength];
  348. int limit;
  349. int i = iVal;
  350. if (iVal < iThat) {
  351. // resDigits[i] = -val.digits[i] & -1;
  352. resDigits[i] = -val.digits[i];
  353. limit = System.Math.Min(val.numberLength, iThat);
  354. for (i++; i < limit; i++) {
  355. // resDigits[i] = ~val.digits[i] & -1;
  356. resDigits[i] = ~val.digits[i];
  357. }
  358. if (i == val.numberLength) {
  359. for (; i < iThat; i++) {
  360. // resDigits[i] = -1 & -1;
  361. resDigits[i] = -1;
  362. }
  363. // resDigits[i] = -1 & ~-that.digits[i];
  364. resDigits[i] = that.digits[i] - 1;
  365. } else {
  366. // resDigits[i] = ~val.digits[i] & ~-that.digits[i];
  367. resDigits[i] = ~val.digits[i] & (that.digits[i] - 1);
  368. }
  369. } else if (iThat < iVal) {
  370. // resDigits[i] = -val.digits[i] & ~~that.digits[i];
  371. resDigits[i] = -val.digits[i] & that.digits[i];
  372. } else {
  373. // resDigits[i] = -val.digits[i] & ~-that.digits[i];
  374. resDigits[i] = -val.digits[i] & (that.digits[i] - 1);
  375. }
  376. limit = System.Math.Min(val.numberLength, that.numberLength);
  377. for (i++; i < limit; i++) {
  378. // resDigits[i] = ~val.digits[i] & ~~that.digits[i];
  379. resDigits[i] = ~val.digits[i] & that.digits[i];
  380. }
  381. for (; i < that.numberLength; i++) {
  382. // resDigits[i] = -1 & ~~that.digits[i];
  383. resDigits[i] = that.digits[i];
  384. }
  385. BigInteger result = new BigInteger(1, resLength, resDigits);
  386. result.CutOffLeadingZeroes();
  387. return result;
  388. }
  389. /** @see BigInteger#or(BigInteger) */
  390. internal static BigInteger or(BigInteger val, BigInteger that) {
  391. if (that.Equals(BigInteger.MinusOne) || val.Equals(BigInteger.MinusOne)) {
  392. return BigInteger.MinusOne;
  393. }
  394. if (that.sign == 0) {
  395. return val;
  396. }
  397. if (val.sign == 0) {
  398. return that;
  399. }
  400. if (val.sign > 0) {
  401. if (that.sign > 0) {
  402. if (val.numberLength > that.numberLength) {
  403. return orPositive(val, that);
  404. } else {
  405. return orPositive(that, val);
  406. }
  407. } else {
  408. return orDiffSigns(val, that);
  409. }
  410. } else {
  411. if (that.sign > 0) {
  412. return orDiffSigns(that, val);
  413. } else if (that.FirstNonzeroDigit > val.FirstNonzeroDigit) {
  414. return orNegative(that, val);
  415. } else {
  416. return orNegative(val, that);
  417. }
  418. }
  419. }
  420. /** @return sign = 1, magnitude = longer.magnitude | shorter.magnitude*/
  421. static BigInteger orPositive(BigInteger longer, BigInteger shorter) {
  422. // PRE: longer and shorter are positive;
  423. // PRE: longer has at least as many digits as shorter
  424. int resLength = longer.numberLength;
  425. int[] resDigits = new int[resLength];
  426. int i = System.Math.Min(longer.FirstNonzeroDigit, shorter.FirstNonzeroDigit);
  427. for (i = 0; i < shorter.numberLength; i++) {
  428. resDigits[i] = longer.digits[i] | shorter.digits[i];
  429. }
  430. for (; i < resLength; i++) {
  431. resDigits[i] = longer.digits[i];
  432. }
  433. BigInteger result = new BigInteger(1, resLength, resDigits);
  434. return result;
  435. }
  436. /** @return sign = -1, magnitude = -(-val.magnitude | -that.magnitude) */
  437. static BigInteger orNegative(BigInteger val, BigInteger that) {
  438. // PRE: val and that are negative;
  439. // PRE: val has at least as many trailing zeros digits as that
  440. int iThat = that.FirstNonzeroDigit;
  441. int iVal = val.FirstNonzeroDigit;
  442. int i;
  443. if (iVal >= that.numberLength) {
  444. return that;
  445. } else if (iThat >= val.numberLength) {
  446. return val;
  447. }
  448. int resLength = System.Math.Min(val.numberLength, that.numberLength);
  449. int[] resDigits = new int[resLength];
  450. //Looking for the first non-zero digit of the result
  451. if (iThat == iVal) {
  452. resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]);
  453. i = iVal;
  454. } else {
  455. for (i = iThat; i < iVal; i++) {
  456. resDigits[i] = that.digits[i];
  457. }
  458. resDigits[i] = that.digits[i] & (val.digits[i] - 1);
  459. }
  460. for (i++; i < resLength; i++) {
  461. resDigits[i] = val.digits[i] & that.digits[i];
  462. }
  463. BigInteger result = new BigInteger(-1, resLength, resDigits);
  464. result.CutOffLeadingZeroes();
  465. return result;
  466. }
  467. /** @return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude) */
  468. static BigInteger orDiffSigns(BigInteger positive, BigInteger negative) {
  469. // Jumping over the least significant zero bits
  470. int iNeg = negative.FirstNonzeroDigit;
  471. int iPos = positive.FirstNonzeroDigit;
  472. int i;
  473. int limit;
  474. // Look if the trailing zeros of the positive will "copy" all
  475. // the negative digits
  476. if (iPos >= negative.numberLength) {
  477. return negative;
  478. }
  479. int resLength = negative.numberLength;
  480. int[] resDigits = new int[resLength];
  481. if (iNeg < iPos) {
  482. // We know for sure that this will
  483. // be the first non zero digit in the result
  484. for (i = iNeg; i < iPos; i++) {
  485. resDigits[i] = negative.digits[i];
  486. }
  487. } else if (iPos < iNeg) {
  488. i = iPos;
  489. resDigits[i] = -positive.digits[i];
  490. limit = System.Math.Min(positive.numberLength, iNeg);
  491. for (i++; i < limit; i++) {
  492. resDigits[i] = ~positive.digits[i];
  493. }
  494. if (i != positive.numberLength) {
  495. resDigits[i] = ~(-negative.digits[i] | positive.digits[i]);
  496. } else {
  497. for (; i < iNeg; i++) {
  498. resDigits[i] = -1;
  499. }
  500. // resDigits[i] = ~(-negative.digits[i] | 0);
  501. resDigits[i] = negative.digits[i] - 1;
  502. }
  503. i++;
  504. } else {// iNeg == iPos
  505. // Applying two complement to negative and to result
  506. i = iPos;
  507. resDigits[i] = -(-negative.digits[i] | positive.digits[i]);
  508. i++;
  509. }
  510. limit = System.Math.Min(negative.numberLength, positive.numberLength);
  511. for (; i < limit; i++) {
  512. // Applying two complement to negative and to result
  513. // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] );
  514. resDigits[i] = negative.digits[i] & ~positive.digits[i];
  515. }
  516. for (; i < negative.numberLength; i++) {
  517. resDigits[i] = negative.digits[i];
  518. }
  519. BigInteger result = new BigInteger(-1, resLength, resDigits);
  520. result.CutOffLeadingZeroes();
  521. return result;
  522. }
  523. /** @see BigInteger#xor(BigInteger) */
  524. internal static BigInteger xor(BigInteger val, BigInteger that) {
  525. if (that.sign == 0) {
  526. return val;
  527. }
  528. if (val.sign == 0) {
  529. return that;
  530. }
  531. if (that.Equals(BigInteger.MinusOne)) {
  532. return val.Not();
  533. }
  534. if (val.Equals(BigInteger.MinusOne)) {
  535. return that.Not();
  536. }
  537. if (val.sign > 0) {
  538. if (that.sign > 0) {
  539. if (val.numberLength > that.numberLength) {
  540. return xorPositive(val, that);
  541. } else {
  542. return xorPositive(that, val);
  543. }
  544. } else {
  545. return xorDiffSigns(val, that);
  546. }
  547. } else {
  548. if (that.sign > 0) {
  549. return xorDiffSigns(that, val);
  550. } else if (that.FirstNonzeroDigit > val.FirstNonzeroDigit) {
  551. return xorNegative(that, val);
  552. } else {
  553. return xorNegative(val, that);
  554. }
  555. }
  556. }
  557. /** @return sign = 0, magnitude = longer.magnitude | shorter.magnitude */
  558. static BigInteger xorPositive(BigInteger longer, BigInteger shorter) {
  559. // PRE: longer and shorter are positive;
  560. // PRE: longer has at least as many digits as shorter
  561. int resLength = longer.numberLength;
  562. int[] resDigits = new int[resLength];
  563. int i = System.Math.Min(longer.FirstNonzeroDigit, shorter.FirstNonzeroDigit);
  564. for (; i < shorter.numberLength; i++) {
  565. resDigits[i] = longer.digits[i] ^ shorter.digits[i];
  566. }
  567. for (; i < longer.numberLength; i++) {
  568. resDigits[i] = longer.digits[i];
  569. }
  570. BigInteger result = new BigInteger(1, resLength, resDigits);
  571. result.CutOffLeadingZeroes();
  572. return result;
  573. }
  574. /** @return sign = 0, magnitude = -val.magnitude ^ -that.magnitude */
  575. static BigInteger xorNegative(BigInteger val, BigInteger that) {
  576. // PRE: val and that are negative
  577. // PRE: val has at least as many trailing zero digits as that
  578. int resLength = System.Math.Max(val.numberLength, that.numberLength);
  579. int[] resDigits = new int[resLength];
  580. int iVal = val.FirstNonzeroDigit;
  581. int iThat = that.FirstNonzeroDigit;
  582. int i = iThat;
  583. int limit;
  584. if (iVal == iThat) {
  585. resDigits[i] = -val.digits[i] ^ -that.digits[i];
  586. } else {
  587. resDigits[i] = -that.digits[i];
  588. limit = System.Math.Min(that.numberLength, iVal);
  589. for (i++; i < limit; i++) {
  590. resDigits[i] = ~that.digits[i];
  591. }
  592. // Remains digits in that?
  593. if (i == that.numberLength) {
  594. //Jumping over the remaining zero to the first non one
  595. for (; i < iVal; i++) {
  596. //resDigits[i] = 0 ^ -1;
  597. resDigits[i] = -1;
  598. }
  599. //resDigits[i] = -val.digits[i] ^ -1;
  600. resDigits[i] = val.digits[i] - 1;
  601. } else {
  602. resDigits[i] = -val.digits[i] ^ ~that.digits[i];
  603. }
  604. }
  605. limit = System.Math.Min(val.numberLength, that.numberLength);
  606. //Perform ^ between that al val until that ends
  607. for (i++; i < limit; i++) {
  608. //resDigits[i] = ~val.digits[i] ^ ~that.digits[i];
  609. resDigits[i] = val.digits[i] ^ that.digits[i];
  610. }
  611. //Perform ^ between val digits and -1 until val ends
  612. for (; i < val.numberLength; i++) {
  613. //resDigits[i] = ~val.digits[i] ^ -1 ;
  614. resDigits[i] = val.digits[i];
  615. }
  616. for (; i < that.numberLength; i++) {
  617. //resDigits[i] = -1 ^ ~that.digits[i] ;
  618. resDigits[i] = that.digits[i];
  619. }
  620. BigInteger result = new BigInteger(1, resLength, resDigits);
  621. result.CutOffLeadingZeroes();
  622. return result;
  623. }
  624. /** @return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude)*/
  625. static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative) {
  626. int resLength = System.Math.Max(negative.numberLength, positive.numberLength);
  627. int[] resDigits;
  628. int iNeg = negative.FirstNonzeroDigit;
  629. int iPos = positive.FirstNonzeroDigit;
  630. int i;
  631. int limit;
  632. //The first
  633. if (iNeg < iPos) {
  634. resDigits = new int[resLength];
  635. i = iNeg;
  636. //resDigits[i] = -(-negative.digits[i]);
  637. resDigits[i] = negative.digits[i];
  638. limit = System.Math.Min(negative.numberLength, iPos);
  639. //Skip the positive digits while they are zeros
  640. for (i++; i < limit; i++) {
  641. //resDigits[i] = ~(~negative.digits[i]);
  642. resDigits[i] = negative.digits[i];
  643. }
  644. //if the negative has no more elements, must fill the
  645. //result with the remaining digits of the positive
  646. if (i == negative.numberLength) {
  647. for (; i < positive.numberLength; i++) {
  648. //resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i])
  649. resDigits[i] = positive.digits[i];
  650. }
  651. }
  652. } else if (iPos < iNeg) {
  653. resDigits = new int[resLength];
  654. i = iPos;
  655. //Applying two complement to the first non-zero digit of the result
  656. resDigits[i] = -positive.digits[i];
  657. limit = System.Math.Min(positive.numberLength, iNeg);
  658. for (i++; i < limit; i++) {
  659. //Continue applying two complement the result
  660. resDigits[i] = ~positive.digits[i];
  661. }
  662. //When the first non-zero digit of the negative is reached, must apply
  663. //two complement (arithmetic negation) to it, and then operate
  664. if (i == iNeg) {
  665. resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]);
  666. i++;
  667. } else {
  668. //if the positive has no more elements must fill the remaining digits with
  669. //the negative ones
  670. for (; i < iNeg; i++) {
  671. // resDigits[i] = ~(0 ^ 0)
  672. resDigits[i] = -1;
  673. }
  674. for (; i < negative.numberLength; i++) {
  675. //resDigits[i] = ~(~negative.digits[i] ^ 0)
  676. resDigits[i] = negative.digits[i];
  677. }
  678. }
  679. } else {
  680. int digit;
  681. //The first non-zero digit of the positive and negative are the same
  682. i = iNeg;
  683. digit = positive.digits[i] ^ -negative.digits[i];
  684. if (digit == 0) {
  685. limit = System.Math.Min(positive.numberLength, negative.numberLength);
  686. for (i++; i < limit && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++)
  687. ;
  688. if (digit == 0) {
  689. // shorter has only the remaining virtual sign bits
  690. for (; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
  691. ;
  692. for (; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
  693. ;
  694. if (digit == 0) {
  695. resLength = resLength + 1;
  696. resDigits = new int[resLength];
  697. resDigits[resLength - 1] = 1;
  698. return new BigInteger(-1, resLength, resDigits);
  699. }
  700. }
  701. }
  702. resDigits = new int[resLength];
  703. resDigits[i] = -digit;
  704. i++;
  705. }
  706. limit = System.Math.Min(negative.numberLength, positive.numberLength);
  707. for (; i < limit; i++) {
  708. resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]);
  709. }
  710. for (; i < positive.numberLength; i++) {
  711. // resDigits[i] = ~(positive.digits[i] ^ -1)
  712. resDigits[i] = positive.digits[i];
  713. }
  714. for (; i < negative.numberLength; i++) {
  715. // resDigits[i] = ~(0 ^ ~negative.digits[i])
  716. resDigits[i] = negative.digits[i];
  717. }
  718. BigInteger result = new BigInteger(-1, resLength, resDigits);
  719. result.CutOffLeadingZeroes();
  720. return result;
  721. }
  722. }
  723. }