LCMP ==== Compare two long integers using unsigned arithmetic Why on Earth would anyone need to compare two unsigned long integers in S*BASIC? Well, there could potentially be many reasons, but the most obvious one is for comparing dates. Under Qdos and SMSQ/E dates are represented as long integers signifying the number of seconds since 1961 Jan 01 00:00:00. Other OSes will have different base dates and may not always use 32 bits to represent them. And perhaps for a good reason, as 32 bits cant represent forever. 4,294,967,294 may seem like a lot of seconds, but in fact, "the last syllable of recorded time" for the QL will arrive on Feb 06, 2097 at 06:28:15! If youre still around, and no one has fixed it by then, expect a spectacular Y2.1K moment all of your own, 'cause thats when the "QL" clock finally runs out of seconds. But there is another critical date long before that, and not that far off either, namely 2029 Jan 19 03:14:07. Thats when the unsigned number range runs out, 2,147,483,647 seconds from 1961 base line. That is the number 2^31-1. Try at the console: PRINT DATE$(2^31-1) Then try: PRINT DATE$(2^31) and see what happens! The next second after 2^31-1 is not 2^31, as one might expect, but -2^31! ie the "negative" number -2,147,483,648. I wont go into the ins and outs of how numbers are represented internally in binary computer systems. If you dont already know, you could lookup "two's complement" in Wikipedia. Back to LCMP. LCMP ignores the convention of signed and unsigned binary numbers and does a simple, so called unsigned, comparison of two binary numbers and returns the result of that comparison. result = LCMP(ulong1, ulong2) result: ulong1 > ulong2 => 1 ulong1 = ulong2 => 0 ulong1 < ulong2 => -1 S*BASIC uses the signed number convention internally, so when you supply a long integer as a parameter it will complain if the namber is above 2^31-1 or below -2^31. However, the DATE function works with unsigned long integers so there we have to use unsigned arithmatic for, eg, date calculations and comparisons. Say you want to find all files between two dates and have to run through a few hundred - or a few thousand - files to find them. Comparing date strings could take rather a long time and would also require some nifty footwork to deal with the month names in all the various languages. LCMP is much quicker and will correctly compare any two dates dates from day dot to (nearly) the end of the century. An alternative is to float the datestamp, adjust the sign, and then do the comparison. For example thus: 100 DEFine FuNction DtCmp(dt1, dt2) 102 LOCal d1, d2 104 d1 = MkFloat(dt1) 106 d2 = MkFloat(dt2) 108 IF d1 > d2: RETurn 1 110 IF d1 = d2: RETurn 0 112 RETurn -1 114 END DEFine DtCmp 116 : 118 : 120 DEFine FuNction MkFloat(n) 122 IF n < 0: RETurn 2^32 + n 124 RETurn n 126 END DEFine MkFloat 128 : (Obviously, youd modify this routine if it were in a loop comparing one date to many..) This method is fast enough for the odd file date comparison, but not ideal if you need to do hundreds or thousands of comparisons. For that use LCMP! Bonus: The MkFloat routine is also perhaps useful for date calculations, eg to calculate the number of days between two dates, eg: 10 CLS 12 d1 = -1 : PRINT DATE$(d1) 14 d2 = DATE : PRINT DATE$(d2) 16 dd = (MkFloat(d1) - MkFloat(d2)) / 86400 18 PRINT INT(dd + 0.5) 20 : prints the number of days between today and doomsday! Program status ============== V0.02, pjw, 2021 Nov 28 Conditions and DISCLAIMER as per Knoware.no