]> www.ginac.de Git - cln.git/blobdiff - src/integer/bitwise/cl_I_logtest.cc
Initial revision
[cln.git] / src / integer / bitwise / cl_I_logtest.cc
diff --git a/src/integer/bitwise/cl_I_logtest.cc b/src/integer/bitwise/cl_I_logtest.cc
new file mode 100644 (file)
index 0000000..586b190
--- /dev/null
@@ -0,0 +1,95 @@
+// logtest().
+
+// General includes.
+#include "cl_sysdep.h"
+
+// Specification.
+#include "cl_integer.h"
+
+
+// Implementation.
+
+#include "cl_I.h"
+#include "cl_DS.h"
+
+cl_boolean logtest (const cl_I& x, const cl_I& y)
+{
+    // Methode:
+    //  Fixnums separat behandeln.
+    //  Sei oBdA x die kürzere der beiden Zahlen (in Digits).
+    //  x echt kürzer und x<0 -> [eines der most signif. intDsize+1 Bits von y ist 1] Ja.
+    //  Beide gleich lang oder x>=0 ->
+    //   Kann mich auf die untersten length(x) Digits beschraenken.
+    //   Mit AND durchlaufen, abbrechen (mit "Ja") falls /=0. Am Ende: Nein.
+      if (fixnump(x))
+        if (fixnump(y))
+          // beides Fixnums
+          { if ((x.word & y.word & cl_combine(0,~(cl_uint)0))==0)
+              return cl_false;
+              else
+              return cl_true;
+          }
+          else
+          // x Fixnum, y Bignum, also ist x echt kürzer
+          { if (FN_L_minusp(x,FN_to_L(x))) return cl_true; // x<0 -> ja.
+            // x>=0. Kombiniere x mit den pFN_maxlength letzten Digits von y.
+           {var const uintD* yLSDptr;
+            var uintL x_ = FN_to_L(x);
+            BN_to_NDS_nocopy(y, ,,yLSDptr=);
+            #if (pFN_maxlength > 1)
+            doconsttimes(pFN_maxlength-1,
+              if (lsprefnext(yLSDptr) & (uintD)x_) return cl_true;
+              x_ = x_ >> intDsize;
+              );
+            #endif
+            if (lsprefnext(yLSDptr) & (uintD)x_) return cl_true;
+            return cl_false;
+          }}
+        else
+        if (fixnump(y))
+          // x Bignum, y Fixnum, analog wie oben, nur x und y vertauscht
+          { if (FN_L_minusp(y,FN_to_L(y))) return cl_true; // y<0 -> ja.
+            // y>=0. Kombiniere y mit den pFN_maxlength letzten Digits von x.
+           {var const uintD* xLSDptr;
+            var uintL y_ = FN_to_L(y);
+            BN_to_NDS_nocopy(x, ,,xLSDptr=);
+            #if (pFN_maxlength > 1)
+            doconsttimes(pFN_maxlength-1,
+              if (lsprefnext(xLSDptr) & (uintD)y_) return cl_true;
+              y_ = y_ >> intDsize;
+              );
+            #endif
+            if (lsprefnext(xLSDptr) & (uintD)y_) return cl_true;
+            return cl_false;
+          }}
+          else
+          // x,y Bignums
+          { var const uintD* xMSDptr;
+            var uintC xlen;
+            var const uintD* yMSDptr;
+            var uintC ylen;
+            BN_to_NDS_nocopy(x, xMSDptr=,xlen=,);
+            BN_to_NDS_nocopy(y, yMSDptr=,ylen=,);
+            // Beachte: xlen>0, ylen>0.
+            if (!(xlen==ylen))
+              // beide verschieden lang
+              { if (xlen<ylen)
+                  { // x ist die echt kürzere DS.
+                    if ((sintD)mspref(xMSDptr,0)<0) // der echt kürzere ist negativ?
+                      return cl_true;
+                    // Der echt kürzere ist positiv.
+                    yMSDptr = yMSDptr mspop (ylen-xlen);
+                  }
+                  else
+                  { // y ist die echt kürzere DS.
+                    if ((sintD)mspref(yMSDptr,0)<0) // der echt kürzere ist negativ?
+                      return cl_true;
+                    // Der echt kürzere ist positiv.
+                    xMSDptr = xMSDptr mspop (xlen-ylen);
+                    xlen = ylen;
+              }   }
+            // Nach gemeinsamen Bits in xMSDptr/xlen/.. und yMSDptr/xlen/..
+            // suchen:
+            return and_test_loop_msp(xMSDptr,yMSDptr,xlen);
+          }
+}