Bit functions in Think Pascal - bit-manipulation

I am converting an old program written on Mac Think Pascal to Pascal on Windows. Think Pascal has functions for bit manipulations, such as
btst(n, i : longint) : boolean
bitxor(i, j : longint) : longint
bclr(n, i : longint) : longint
bset(n, i : longint) : longint
...and others. If you know what these functions do, please help.
I have found some related information, for example "Porting to GNU Pascal from traditional Macintosh Pascal compilers". This document has implementations of the bit functions using bitwise operators like and, or, shr and shl. However, I am not sure that the description in the document is correct.
I know approximate meaning of the functions:
btst(n,i) is True, if i-th bit of n is 1, and False otherwise
bitxor(i,j) is bitwise 'xor'
bclr(n, i) sets i-th bit of n to 0
bset(n, i) sets i-th bit of n to 1
However, I don't know what is the correct order of variables in the functions (e.g. btst(n,i) or btst(i,n)). Also, how bits are numbered? From left to right, starting from 0 or 1? Thank you for any help on these four functions.

(sorry, needed some more room)
The build in Free Pascal of Dev Pascal 1.9.2 is essentially a beta, and very, very old, and lacks such features since it is 2002 era. But dev-pascal can be used with newer FPC's I'm told. Lazarus is pretty close to recompiling the thing itself :_)
Put {$mode macpas} after the program and/or "interface" line (in an unit). Commandline is also possible, -Mmacpas (goes for all compiled by that invocation of the compiler unless overruled by $mode in source)
The functions you name are supported in mode MacPasc, but bitxor is called bxor(). Afaik MacPascal mostly models CodeWarrior Pascal, but since that is mostly a superset Think afaik usually works fine. Some Thinkisms were added.
Since macpascal knowledge is fairly rare, you might want to subscribe either to the main fpc list main fpc list or the Mac Pascal List.
The General Lazarus Forum is also abused for FPC purposes, though I expect less people knowledgeable about old Apple dialects there.

Bits are numbered from 0 to 7 in a byte or 0 to 15 in a word. Bit 0 is the rightmost bit. So, if Bit 0 is 1 and all other bits are 0, the integer value of the byte or word is 1.

Related

What is std::__lg?

As title I don't know what is std::__lg mean after google it?And what exactly this line do : int n = std::__lg(block_sz - pos_l + 1);
It's helper to compute the 2-based logarithm of integer number, i.e. it return the index of highest set bit in the number (or -1 for 0).
I.e. for 1 it will return 0, for 16 it will return 4, for 1024 it will return 10, etc.
This can be used to efficiently predict the pre-allocated size for arrays, round to the nearest power of 2 and thing like that.
Note, that as any other function starting with __, it's internal function of the compiler or the library, so you should not rely on its existence, such code wouldn't be portable. Other implementations of std library can come with completely solution and different names of similar helpers (if they use something similar at all).
POSIX provides similar function - ffs(), there are also ffsl and ffsll (see the same page) which is GNU extension and work with long and long long respectively.
For the question from comment - how to use it from Java. Because of the above it's not good idea first, secondly it would require JNI wrapper for this. And third but most important - there is no reason for this actually. Java already provides similar methods Integer.heghestOneBit(), although note it returns +1 in comparison to described std::__lg, i.e. 0 for 0, 1 for 1, 11 for 1024, etc.
It's an identifier used internally by your compiler (very likely GCC), because all identifiers with double underscores belong to the compiler implementation.
Nowhere in your own code should something like __lg be seen or used. Use the interface of the standard library, not its implementation. If your own code directly uses __lg, then you have no guarantee that the code will compile or do the right thing with any other compiler or even with any other version of the same compiler.
As the C++ standard says at ยง2.10 [lex.name]:
Each identifier that contains a double underscore __ or begins
with an underscore followed by an uppercase letter is reserved to the
implementation for any use.
As for what that GCC thing actually is, just look at the source code which a Google search for "std::__lg" turns up.
Depending on the actual types of block_sz and pos_l, it should be either this:
/// This is a helper function for the sort routines and for random.tcc.
// Precondition: __n > 0.
template<typename _Size>
inline _Size
__lg(_Size __n)
{
_Size __k;
for (__k = 0; __n != 0; __n >>= 1)
++__k;
return __k - 1;
}
Or this:
inline int
__lg(int __n)
{ return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); }
Now, __CHAR_BIT__ is like the standard CHAR_BIT macro. As GCC documentation says:
Defined to the number of bits used in the representation of the char
data type. It exists to make the standard header given numerical
limits work correctly. You should not use this macro directly;
instead, include the appropriate headers.
__builtin_clz is another GCC-specific function. Again, GCC documentation explains its purpose:
Returns the number of leading 0-bits in x, starting at the most
significant bit position. If x is 0, the result is undefined.
I think if you need such functionality, then it's trivial to write it yourself. In fact, the question is why you need it in the first place. The real answer to your actual problem probably lies in the code around the int n = std::__lg(block_sz - pos_l + 1); line.
Things to keep in mind:
Do not use anything with two consecutive underscores in your own code.
GCC is open source, so the internal implementation of special functions or macros is not secret but can easily be browsed online.

How to implement a bit array in Modern Fortran?

I am new to Fortran 2008 and am trying to implement a Sieve of Atkin. In C++ I implemented this using a std::bitset but was unable to find anything in Fortran 2008 that serves this purpose.
Can anyone point me at any example code or explain an implementation strategy for one?
Standard Fortran doesn't have a precise analogue of what I understand std:bitset to be -- though I grant you my understanding may be defective. Generally, and if you want to stick to standard Fortran, you would use integers as sets of bits. If one integer doesn't have enough bits for your purposes, use arrays of integers. This does mean, though, that the responsibility for tracking where, say, the 307-th bit of your bitset is falls on you
Prior to the 2008 standard you have functions such as bit_size, iand, ibset, btest and others (see your compiler documentation or Google for language references, or try the Intel Fortran documentation) for bit manipulation.
If you are unfamiliar with Fortran's boz literals then familiarise yourself with them. You can, for example, set the bits of an integer using a statement such as this
integer :: mybits
...
mybits = b'00000011000000100000000000001111'
With the b edit descriptor you can read and write binary literals too. For example the statements
write(*,*) mybits
write(*,'(b32.32)') mybits
will produce the output
50462735
00000011000000100000000000001111
If you can lay your hands on a modern-enough compiler then you will find that the 2008 standard added new bit-twiddling functions such as bge, bgt, dshiftl, iall and a whole lot more. These are defined for input arguments which are integer arrays or integers, but I don't have any experience of using them to pass on.
This should be enough to get you started.
Fortran has bit intrinsics for manipulating the bits of default integers. Bit arrays are straightforward to build off that...
Determine how many bits you need, divide by number of bits in default integer, allocate an integer array of default kind of the size you computed +1 if the modulo of the division was non-zero, and you're essentially done. The bit intrinsics are well covered in Metcalf and Reid.
What you may want could look like:
program test
logical,allocatable:: flips(:)
...
allocate(flips(ntris),status=err)
call tris(ntris,...,flips)
...
end
subroutine tris(nnewtris, ...,flips)
logical flips(nnewtris)
...
if(flips(i)) then
...
end if
return
end

Ada to C++: Pass an unsigned 64-bit value

I need to pass 2 pieces of data from an Ada program to some C++ code for processing.
Data - double.
Time - unsigned 64 bits.
I was able to make a procedure in Ada that worked with my C++ method using a Long_Float (double in C++) and Integer (int in C++, obviously not 64-bits though).
I used the following code (code not on me so syntax might be slightly off):
procedure send_data (this : in hidden_ptr; data : in Long_Float; time : in Integer);
pragma import (CPP, send_data, "MyClass::sendData");
Now that that's working, I'm trying to expand the time to the full 64-bits and ideally would like to have an unsigned long long on the C++ side. I don't see any types in Ada that match that so I created my own type:
type U64 is mod 2 ** 64;
When using that type with my send_data method I get an error saying there are no possible ways to map that type to a C++ type (something along those lines, again don't have the code or exact error phrase on me).
Is there a way to pass a user-defined type in Ada to C++? Perhaps there's another type in Ada I can use as an unsigned 64-bit value that would work? Is there a way to pass the address of my U64 type as a parameter to the C++ method instead if that's easier? I'm using the green hills adamulti compiler v3.5 (very new to ada, not sure if that info helps or not). Examples would be greatly appreciated!
As an addendum to #KeithThompson's comment/answer...
Ada's officially supported C interface types are in Interfaces.C, and there's no extra-long int or unsigned in there (in the 2005 version. Is the 2012 version official yet?).
You did the right thing to work around it. If your compiler didn't support that, more drastic measures will have to be taken.
The first obvious thing to try is to pass the 64-bit int by reference. That will require changes on the C side though.
I know C/C++ TIME structs tend to be 64-bit values, defined as unioned structs. So what you could do is define an Ada record to mimic one of those C structs, make sure it gets laid out the way C would (eg: with record representation and size clauses), and then make that object what your imported routine uses for its parameter.
After that you'll have to pull nasty parameter tricks. For example, you could try changing the Ada import's side of the parameter to a 64-bit float, unchecked_converting the actual parameter into a 64-bit float, and trying to pass it that way. The problem there is that a lot of CPU's pass floats in different registers than ints. So that likely won't work, and if it does it most certianly isn't portable.
There may well be other ways to fake it out, if you figure out how your compiler's CPP calling convention works. For example, if it uses two adajacent 32-bit registers to pass 64-bit ints, you could split your Ada 64-bit int into two and pass it in two parameters on the Ada side. If it passes 64-bit values by reference, you could just tell the Ada side that you're passing a pointer to your U64. Again, these solutions won't be portable, but they would get you going.
Put_Line("First = " & Interfaces.C.long'Image(Interfaces.C.long'First));
Put_Line("Last = " & Interfaces.C.long'Image(Interfaces.C.long'Last));
result:
First = -9223372036854775808
Last = 9223372036854775807

Default real kind porting problem

I've ported some Fortran code from Fortran PowerStation(4.0) to the Fortran 11(2003) compiler. In order to maintain double and real values between the old and new compiler, I changed properties>fortran>data>"Default Read Kind" from 4 to 8. Now the problem is that the global variables are not maintaining data from one file to other.
Suppose I create a real*8 variable called abc in one file as a global variable (COMMON/test/abc). It is modified in one file and used in another file. When inspecting the value of the abc variable in the second file, it is found not to contain the modified data. This happens only when I change "Default Real Kind" to 8.
Are there any other options I need to modify from the properties window?
Please give a solution. Thanks in advance.
I'm a bit unclear about what compiler you are using, what modifications you have made and so forth, so my answer is a bit hesitant.
I'm not sure that changing the default real kind from 4 to 8 does maintain values as you think it does. You seem to think that real(kind=4) on your old compiler means the same as real(kind=8) on your new compiler. This may be true, but it seems a bit unlikely to me.
However, don't fall into the trap of thinking that real(kind=4) must mean a 4-byte IEEE compliant floating-point number, or that real(kind=8) must mean an 8-byte IEEE fp number. This is true for most compilers, certainly for all the compilers I've used recently, but it's not required by the Fortran standard. Your old compiler may have meant something different from what your new compiler means.
Finally, I usually experience problems with common blocks when I change real number sizes in Fortran programs. The best solution is to replace common blocks with module variables. If you can't do that, check the common declarations very carefully, bearing in mind that common is an instruction to the compiler about how to lay variables out in memory. If you change the size of a variable in one declaration of the common block but not in another you will have problems.
Regards
Mark

How to handle arbitrarily large integers

I'm working on a programming language, and today I got the point where I could compile the factorial function(recursive), however due to the maximum size of an integer the largest I can get is factorial(12). What are some techniques for handling integers of an arbitrary maximum size. The language currently works by translating code to C++.
If you need larger than 32-bits you could consider using 64-bit integers (long long), or use or write an arbitrary precision math library, e.g. GNU MP.
If you want to roll your own arbitrary precision library, see Knuth's Seminumerical Algorithms, volume 2 of his magnum opus.
If you're building this into a language (for learning purposes I'd guess), I think I would probably write a little BCD library. Just store your BCD numbers inside byte arrays.
In fact, with today's gigantic storage abilities, you might just use a byte array where each byte just holds a digit (0-9). You then write your own routine to add, subtract multiply and divide your byte arrays.
(Divide is the hard one, but I bet you can find some code out there somewhere.)
I can give you some Java-like psuedocode but can't really do C++ from scratch at this point:
class BigAssNumber {
private byte[] value;
// This constructor can handle numbers where overflows have occurred.
public BigAssNumber(byte[] value) {
this.value=normalize(value);
}
// Adds two numbers and returns the sum. Originals not changed.
public BigAssNumber add(BigAssNumber other) {
// This needs to be a byte by byte copy in newly allocated space, not pointer copy!
byte[] dest = value.length > other.length ? value : other.value;
// Just add each pair of numbers, like in a pencil and paper addition problem.
for(int i=0; i<min(value.length, other.value.length); i++)
dest[i]=value[i]+other.value[i];
// constructor will fix overflows.
return new BigAssNumber(dest);
}
// Fix things that might have overflowed 0,17,22 will turn into 1,9,2
private byte[] normalize(byte [] value) {
if (most significant digit of value is not zero)
extend the byte array by a few zero bytes in the front (MSB) position.
// Simple cheap adjust. Could lose inner loop easily if It mattered.
for(int i=0;i<value.length;i++)
while(value[i] > 9) {
value[i] -=10;
value[i+1] +=1;
}
}
}
}
I use the fact that we have a lot of extra room in a byte to help deal with addition overflows in a generic way. Can work for subtraction too, and help on some multiplies.
There's no easy way to do it in C++. You'll have to use an external library such as GNU Multiprecision, or use a different language which natively supports arbitrarily large integers such as Python.
Other posters have given links to libraries that will do this for you, but it seem like you're trying to build this into your language. My first thought is: are you sure you need to do that? Most languages would use an add-on library as others have suggested.
Assuming you're writing a compiler and you do need this feature, you could implement integer arithmetic functions for arbitrarily large values in assembly.
For example, a simple (but non-optimal) implementation would represent the numbers as Binary Coded Decimal. The arithmetic functions could use the same algorithms as you'd use if you were doing the math with pencil and paper.
Also, consider using a specialized data type for these large integers. That way "normal" integers can use the standard 32 bit arithmetic.
My prefered approach would be to use my current int type for 32-bit ints(or maybe change it to internally to be a long long or some such, so long as it can continue to use the same algorithms), then when it overflows, have it change to storing as a bignum, whether of my own creation, or using an external library. However, I feel like I'd need to be checking for overflow on every single arithmetic operation, roughly 2x overhead on arithmetic ops. How could I solve that?
If I were implement my own language and want to support arbitrary length numbers, I will use a target language with the carry/borrow concept. But since there is no HLL that implements this without severe performance implications (like exceptions), I will certainly go implement it in assembly. It will probably take a single instruction (as in JC in x86) to check for overflow and handle it (as in ADC in x86), which is an acceptable compromise for a language implementing arbitrary precision. Then I will use a few functions written in assembly instead of regular operators, if you can utilize overloading for a more elegant output, even better. But I don't expect generated C++ to be maintainable (or meant to be maintained) as a target language.
Or, just use a library which has more bells and whistles than you need and use it for all your numbers.
As a hybrid approach, detect overflow in assembly and call the library function if overflow instead of rolling your own mini library.