Где я могу найти мягкие многократно и разделить алгоритмы?

StackOverflow https://stackoverflow.com/questions/2390354

Вопрос

Я работаю над микроконтроллером без аппаратного обеспечения умножения и разделите. Мне нужно готовить программные алгоритмы для этих основных операций, которые являются хорошим балансом компактного размера и эффективности. Мой порт C компилятора нанимает эти ALGO, а не сами разработчики C.

Мой Google-Fu до сих пор поворачивается в основном шум на этой теме.

Кто-нибудь может указать мне что-то информативное? Я могу использовать add / sub и shift инструкции. Альгос на основе таблиц, находящихся на основе ALGOS, может также работать для меня, но я немного беспокоюсь о затягивании в спине компилятора ... Хм, так сказать.

Это было полезно?

Решение

Вот простой алгоритм умножения:

  1. Начните с самого правого бита умножителя.

  2. Если бит в мультипликате 1, добавьте мультипликацию

  3. Сдвиг мультипликации на 1

  4. Перейдите к следующему биту в мультипликции и вернитесь к шагу 2.

И вот алгоритм разделения:

  1. Если делитель больше, чем дивиденд, остановитесь.

  2. В то время как реестр дивизора меньше, чем реестр дивиденда, сдвиг осталось.

  3. Переведите реестр делителя прямо на 1.

  4. Вычитайте реестр Divisor из реестра дивидендов и измените бит до 1 в реестр результата на бит, который соответствует общему количеству сдвигов, сделанных для реестра делителя.

  5. Начните на шаге 1 с реестром Divisor в исходном состоянии.

Конечно, вам нужно будет поставить чек для разделения на 0, но он должен работать.

Эти алгоритмы, конечно, предназначены только для целых чисел.

Другие советы

Моя любимая ссылка на такие вещи, как это, доступно в форме книги:

http://www.hackersdelight.org/

Также вы не можете ошибоваться с TaoCP: http://www-cs-faculty.stanford.edu/~uno/taocp.html.

Вот алгоритм разделения: http://www.prasannatech.net/2009/01/division-without-division-operator_24.html.

Я предполагаю, что мы говорим о INTS?

Если нет поддержки аппаратного обеспечения, вам придется реализовать свое собственное значение для разделения по нулю.

(Мне не повезло быстро найти алгоритм умножения, но я буду смотреть, если кто-то другой не найдет его).

Один простой и довольно исполнительный алгоритм умножения для целых чисел Русское крестьянское умножение.

Для рационализации вы можете попробовать двоичный Обозначение цитаты, для какого разделения легче, чем обычно.

Оказывается, у меня все еще есть какой-то старый код ассемблера 68000 для длительного размножения и длительного дивижения. 68000 код довольно чистый и простой, поэтому должно быть легко перевести на ваш чип.

У68000 было умноженно и разделить инструкции IIRC - я думаю, что они были написаны как учебное упражнение.

Решил просто поставить код здесь. Добавлены комментарии и, в процессе исправили проблему.

;
; Purpose  : division of longword by longword to give longword
;          : all values signed.
; Requires : d0.L == Value to divide
;          : d1.L == Value to divide by
; Changes  : d0.L == Remainder
;          : d2.L == Result
;          : corrupts d1, d3, d4
;

        section text

ldiv:   move    #0,d3     ; Convert d0 -ve to +ve - d3 records original sign
        tst.l   d0
        bpl.s   lib5a
        neg.l   d0
        not     d3
lib5a:  tst.l   d1        ; Convert d1 -ve to +ve - d3 records result sign
        bpl.s   lib5b
        neg.l   d1
        not     d3
lib5b:  tst.l   d1        ; Detect division by zero (not really handled well)
        bne.s   lib3a
        rts
lib3a:  moveq.l #0,d2     ; Init working result d2
        moveq.l #1,d4     ; Init d4
lib3b:  cmp.l   d0,d1     ; while d0 < d1 {
        bhi.s   lib3c
        asl.l   #1,d1     ; double d1 and d4
        asl.l   #1,d4
        bra.s   lib3b     ; }
lib3c:  asr.l   #1,d1     ; halve d1 and d4
        asr.l   #1,d4
        bcs.s   lib3d     ; stop when d4 reaches zero
        cmp.l   d0,d1     ; do subtraction if appropriate
        bhi.s   lib3c
        or.l    d4,d2     ; update result
        sub.l   d1,d0
        bne.s   lib3c
lib3d:                    ; fix the result and remainder signs
;       and.l   #$7fffffff,d2  ; don't know why this is here
        tst     d3
        beq.s   lib3e
        neg.l   d2
        neg.l   d0
lib3e:  rts

;
; Purpose  : Multiply long by long to give long
; Requires : D0.L == Input 1
;          : D1.L == Input 2
; Changes  : D2.L == Result
;          : D3.L is corrupted
;

lmul:   move    #0,d3       ; d0 -ve to +ve, original sign in d3
        tst.l   d0
        bpl.s   lib4c
        neg.l   d0
        not     d3
lib4c:  tst.l   d1          ; d1 -ve to +ve, result sign in d3
        bpl.s   lib4d
        neg.l   d1
        not     d3
lib4d:  moveq.l #0,d2       ; init d2 as working result
lib4a:  asr.l   #1,d0       ; shift d0 right
        bcs.s   lib4b       ; if a bit fell off, update result
        asl.l   #1,d1       ; either way, shift left d1
        tst.l   d0
        bne.s   lib4a       ; if d0 non-zero, continue
        tst.l   d3          ; basically done - apply sign?
        beq.s   lib4e       ; was broken! now fixed
        neg.l   d2
lib4e:  rts
lib4b:  add.l   d1,d2      ; main loop body - update result
        asl.l   #1,d1
        bra.s   lib4a

Кстати - я никогда не выяснил, нужно ли преобразовать все в позитив в начале. Если вы осторожны с операциями сдвига, это может быть избежать накладных расходов.

Чтобы размножаться, добавьте частичные продукты из смещенного мультипликала в аккумулятор IFF соответствующего бита в мультипликате. Сдвиньте мультипликацию и множитель в конце цикла, тестирование умножителя и 1, чтобы увидеть, следует ли сделать добавление.

Чипы серии Microchip Picmicro 16FXXX не имеют многократного или разделения. Возможно, некоторые из мягких многократных и мягких делящихся процедур для него могут быть перенесены в ваш MCU.

PIC Microcontroller Основные методы умножения математики

PIC Microcontroller Основные методы математического разделения

Также проверьте «Метод Ньютона» для разделенияОтказ Я думаю, что этот метод дает наименьшее исполняемое размер любого алгоритма деления, который я когда-либо видел, хотя объяснение делает его звуком более сложным, чем на самом деле. Я слышу, что некоторые ранние суперкомпьютеры Cray использовали метод Ньютона для разделения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top