class ZXLib::Math
A module with the ZXReal
struct definition and ZX-Spectrum FP helpers.
Macros
can be used to convert 32-bit integers to and from floating point values.
Example:
require('zxlib/math') class TestMath include Z80 include Z80::TAP ZXReal = ZXLib::Math::ZXReal chan_open addr 0x1601 export :auto start ld a, 2 call chan_open ld hl, pi call math.print_fp_hl ret pi data ZXReal, Math::PI import :math, ZXLib::Math end
Constants
- EPSILON
ZX-Spectrum's float number epsilon
Public Class Methods
Converts num
to a ZX-Spectrum's real number encoded as a 5-byte binary string.
simplified_int
indicates if the integers in the range of -65535..65535 should be stored in a simplified integer form.
Returns binary string.
# File lib/zxlib/math.rb, line 54 def self.pack_number(num, simplified_int=true) sgn = num < 0 if simplified_int && num == num.truncate && -65535 <= num && num <= 65535 [0, sgn ? -1 : 0, num, 0].pack('CcvC') else m = (sgn ? -num : num).to_f e = (::Math.log2(m)+1.0).floor raise "overflow error" if e > 127 if e < -127 [0].pack('C')*5 else # m = m*(2**-e) if e < 0 m = m*(1<< (-e)) else m = m/(1<<e) end [ e + 128, sgn ? (m*(1<<32)).truncate : (m*(1<<32)).truncate ^ (1<<31) ].pack('CN') end end end
Converts a ZX-Spectrum's real number as a 5-byte binary string to Numeric
value.
simplified_int_as_fixnum
indicates if the number encoded as a simple integer should be returned as a Fixnum
.
Returns Float
or Fixnum
.
# File lib/zxlib/math.rb, line 87 def self.unpack_number(bin, simplified_int_as_fixnum=true) raise ArgumentError unless String === bin && bin.bytesize >= 5 e, m = bin.unpack('CN') if e.zero? sgn, val, z = bin.unpack('xcvC') if z.zero? val = case sgn when 0 then val when -1 then val-0x10000 else raise "simplified binary integer parse error" end val = val.to_f unless simplified_int_as_fixnum return val end end e -= 128 sgn = if (m & (1<<31)).zero? m |= (1<<31) false else true end val = m.to_f/(1<<32) # m = m/(2**-e) val = if e < 0 val/(1<< (-e)) else val*(1<<e) end sgn ? -val : val end
Public Instance Methods
Call print_fp_hl
with hl
pointing to the 1st byte of a ZXReal
number to print that number to the currently opened channel.
After return the ZF flag can be inspected to check if the number was 0.
# File lib/zxlib/math.rb, line 305 isolate :print_fp_hl, use: rom do ld a, [hl] # get floating point from (hl) inc hl ld e, [hl] inc hl ld d, [hl] inc hl ld c, [hl] inc hl ld b, [hl] inc hl push hl # save hl ld l, a # check if zero (return in Z flag) ora e ora d ora c ora b push af ld a, l call rom.stk_store # store number on the calculator's stack call rom.print_fp # print number from the stack pop af pop hl ret end