Math Processor Unit Library

libmpu – library of arithmetic functions for integer, real, and complex numbers of increased digit capacity

16 Commits   0 Branches   2 Tags
author: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300 committer: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300 commit: 3c780c88a0a0e98f7bb1ceaf7843c4560d2e0ce4 parent: 31f615c1e5a07398bdd68c74b81fbe64c45f169a
Commit Summary:
Man pages for one-bit shift operations
Diffstat:
1 file changed, 151 insertions, 0 deletions
diff --git a/man/shifts.3mpu b/man/shifts.3mpu
new file mode 100644
index 0000000..00743c9
--- /dev/null
+++ b/man/shifts.3mpu
@@ -0,0 +1,163 @@
+.\" Copyright 2024 Andrew V.Kosteltsev (kx@radix-linux.su)
+.\"
+.\"
+.TH shifts 3  "December 27, 2024" "libmpu" "LibMPU Programmer's Manual"
+.SH NAME
+\fBishl\fP, \fBishr\fP, \fBisal\fP, \fBisar\fP \- one\-bit shifts
+.SH SYNOPSIS
+.nf
+.B #include <libmpu.h>
+.PP
+.BI "void ishl( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void ishr( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isal( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isar( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.fi
+.SH DESCRIPTION
+For one\-bit shift operations, the input operand is a variable of size \fBnb\fP bytes located
+at address \fBa\fP, the result is placed in a variable of the same size located at address \fBc\fP.
+The spaces occupied by the input and output variable in memory may overlap, either partially or
+completely, which does not affect the correctness of the result obtained. The content of the
+variable located at address \fBa\fP will remain unchanged after the operation if the space
+occupied by it does not overlap with the space occupied by variable \fBc\fP.
+.PP
+When performing shift operations, the carry flag \fBC\fP always contains the value of the last
+putted forward bit. There are the following types of shift operations:
+.PP
+
+.RS 3
+    SHL \- logical unsigned shift to the left by one bit.
+.RE
+.RS 3
+    SHR \- logical unsigned shift to the right by one bit.
+.RE
+.RS 3
+    SAL \- arithmetic shift to the left by one bit.
+.RE
+.RS 3
+    SAR \- arithmetic shift to the right by one bit.
+.RE
+
+.PP
+The following tables illustrate the execution of the operations \fBishl\fP, \fBishr\fP.
+.nf
+.sp
+      ┌────────────────┬───┬───────────────────┬────────────┐
+      │ SHL(<<):       │ C │   operand value   │  filling   │
+      ├────────────────┼───┼───────────────────┼────────────┤
+      │ before         │   │      10110111     │     0      │
+      ├────────────────┼───┼───────────────────┼────────────┤
+      │ after          │ 1 │      01101110     │            │
+      └────────────────┴───┴───────────────────┴────────────┘
+
+      ┌────────────────┬────────────┬───────────────────┬───┐
+      │ SHR(>>):       │  filling   │   operand value   │ C │
+      ├────────────────┼────────────┼───────────────────┼───┤
+      │ before         │     0      │      10110111     │   │
+      ├────────────────┼────────────┼───────────────────┼───┤
+      │ after          │            │      01011011     │ 1 │
+      └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+The tables show that any logical shift always results in a 0 being pushed into the vacated space. 
+The overflow flag \fBO\fP is set if the operand has changed sign as a result of the operation.
+.PP
+The left arithmetic shift operation \fBisal\fP operates in the same way as \fBishl\fP (0 is
+also moved to the empty space on the right). The right arithmetic shift operation works
+differently: the sign bit of the original operand is copied to the empty position on the left.
+The action of the \fBisal\fP and \fBisar\fP operations is shown in the following tables.
+.nf
+.sp
+      ┌────────────────┬───┬───────────────────┬────────────┐
+      │ SAL(<<):       │ C │   operand value   │  filling   │
+      ├────────────────┼───┼───────────────────┼────────────┤
+      │ before         │   │      10110111     │     0      │
+      ├────────────────┼───┼───────────────────┼────────────┤
+      │ after          │ 1 │      01101110     │            │
+      └────────────────┴───┴───────────────────┴────────────┘
+
+      ┌────────────────┬────────────┬───────────────────┬───┐
+      │ SAR(>>):       │  filling   │   operand value   │ C │
+      ├────────────────┼────────────┼───────────────────┼───┤
+      │ before         │   sign(1)  │      10110111     │   │
+      ├────────────────┼────────────┼───────────────────┼───┤
+      │ after          │            │      11011011     │ 1 │
+      └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+The overflow flag for the \fBisal\fP operation is set in the same way as for the \fBishl\fP
+operation. When performing an \fBisar\fP operation, the operand cannot change its sign. Repeated
+shifting of \fBisar\fP may eventually cause a loss of value, and a positive number will be shifted
+to 0 and a negative number to -1. Therefore, the overflow flag \fBO\fP for the \fBisar\fP operation
+is reset to 0.
+.PP
+When performing \fBisal\fP, \fBisar\fP, \fBishl\fP, \fBishr\fP operations, the parity \fBP\fP,
+sign \fBS\fP and zero \fBZ\fP flags are also set. The carry flag from the lowest tetrad \fBA\fP
+is not defined and is simply reset to 0.
+.PP
+Left shift can be used to double numbers, and right shift can be used to divide by 2. These operations
+are much faster than multiplication and division operations. Dividing odd numbers (such as 5 or 7) in
+half forms smaller values (2 or 3, respectively) and sets the carry flag \fBC\fP to 1. In doing so,
+\fBC\fP actually contains the remainder of the division. This use of shift operations requires control
+of the overflow flag \fBO\fP. For simplicity, consider flag control on 4\-bit signed variables:
+.SS Examples with 4\-bit operands:
+\fBMultiplying by 2\fP:
+.nf
+SAL(0111) =  7; result = 1110 = -2, mistake, there must be 14, CF = 0, OF = 1
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SHR(1000) = -8; result = 0100 =  4, mistake, there must be -4, CF = 0, OF = 1
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SAR(1000) = -8; result = 1100 = -4, exactly, CF = 0, OF = 0
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SAR(0111) =  7; result = 0011 =  3, remainder 1 (see carry flag C), exactly, CF = 1, OF = 0
+.fi
+.sp
+.SH EXAMPLES
+.nf
+.sp
+#include <libmpu.h>
+#include <stdio.h>
+
+int main( void )
+{
+  int  rc = 0;
+
+  __mpu_init();
+  __mpu_extra_warnings = 1;
+
+  {
+    mpu_int128_t   c, a;
+    int            nb = NB_I8;
+    __mpu_char8_t  sc[32], sa[32];
+
+    iatoi( a, "0b10110111", nb ); /* evaluate the A variable */
+
+    ishl( c, a, nb );
+    iitoa( sa, a, RADIX_BIN, LOWERCASE, nb ); /* convert A value to ASCII string SA */
+    iitoa( sc, c, RADIX_BIN, LOWERCASE, nb ); /* convert C value to ASCII string SC */
+    printf( "a = %s;\n", sa ); /* c = 0b10110111; */
+    printf( "c = %s;\n", sc ); /* c = 0b01101110; */
+    printf( "carry      = %d;\n", __mpu_gtc() );  /* Carry Flag    */
+    printf( "overflow   = %d;\n", __mpu_gto() );  /* Overflow Flag */
+  }
+
+  __mpu_free_context();
+
+  return( rc );
+}
+.fi
+.SH SEE ALSO
+.BR iadd(3),
+.BR iadc(3),
+.BR isub(3),
+.BR isbb(3).
+