ncr_HL_DE.z80 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. ;Written by Zeda
  2. ; Requires
  3. ; mul16 ;BC*DE ==> DEHL
  4. ; DEHL_Div_BC ;DEHL/BC ==> DEHL
  5. ncr_HL_DE:
  6. ;"n choose r", defined as n!/(r!(n-r)!)
  7. ;Computes "HL choose DE"
  8. ;Inputs: HL,DE
  9. ;Outputs:
  10. ; HL is the result
  11. ; "HL choose DE"
  12. ; carry flag reset means overflow
  13. ;Destroys:
  14. ; A,BC,DE,IX
  15. ;Notes:
  16. ; Overflow is returned as 0
  17. ; Overflow happens if HL choose DE exceeds 65535
  18. ; This algorithm is constructed in such a way that intermediate
  19. ; operations won't erroneously trigger overflow.
  20. ;66 bytes
  21. ld bc,1
  22. or a
  23. sbc hl,de
  24. jr c,ncr_oob
  25. jr z,ncr_exit
  26. sbc hl,de
  27. add hl,de
  28. jr c,$+3
  29. ex de,hl
  30. ld a,h
  31. or l
  32. push hl
  33. pop ix
  34. ncr_exit:
  35. ld h,b
  36. ld l,c
  37. scf
  38. ret z
  39. ncr_loop:
  40. push bc \ push de
  41. push hl \ push bc
  42. ld b,h
  43. ld c,l
  44. call mul16 ;BC*DE ==> DEHL
  45. pop bc
  46. call DEHL_Div_BC ;result in DEHL
  47. ld a,d
  48. or e
  49. pop bc
  50. pop de
  51. jr nz,ncr_overflow
  52. add hl,bc
  53. jr c,ncr_overflow
  54. pop bc
  55. inc bc
  56. ld a,b
  57. cp ixh
  58. jr c,ncr_loop
  59. ld a,ixl
  60. cp c
  61. jr nc,ncr_loop
  62. ret
  63. ncr_overflow:
  64. pop bc
  65. xor a
  66. ld b,a
  67. ncr_oob:
  68. ld h,b
  69. ld l,b
  70. ret
  71. DEHL_Div_BC:
  72. #include "math/DEHL_Div_BC_special.z80"