implements SQRT PREC DEFAULT TYPE TIME DATE TICKS

This commit is contained in:
Gwenhael Le Moine 2021-11-18 15:44:09 +01:00
parent db02abb114
commit 1e4dafb1d4
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
7 changed files with 129 additions and 7 deletions

View file

@ -1,12 +1,30 @@
require 'bigdecimal/math'
require_relative './language/general'
require_relative './language/mode'
require_relative './language/operations'
require_relative './language/program'
require_relative './language/stack'
require_relative './language/time-date'
module Rpn
module Core
module_function
include BigMath
def precision
@precision
end
def precision=( value )
@precision = value
end
def init
@precision = 12 # default precision for math operations
end
def stack_extract( stack, needs )
raise 'Not enough elements' if stack.size < needs.size

View file

@ -38,7 +38,7 @@ module Rpn
add( '/', proc { |stack| Rpn::Core::Operations.divide( stack ) } )
add( 'inv', proc { |stack| Rpn::Core::Operations.inverse( stack ) } )
add( '^', proc { |stack| Rpn::Core::Operations.power( stack ) } )
add( 'sqrt', proc { |stack| Rpn::Core.__todo( stack ) } ) # rpn_square root
add( 'sqrt', proc { |stack| Rpn::Core::Operations.sqrt( stack ) } )
add( 'sq', proc { |stack| Rpn::Core.__todo( stack ) } ) # rpn_square
add( 'abs', proc { |stack| Rpn::Core.__todo( stack ) } ) # absolute value
add( 'dec', proc { |stack| Rpn::Core.__todo( stack ) } ) # decimal representation
@ -75,10 +75,10 @@ module Rpn
add( 'std', proc { |stack| Rpn::Core.__todo( stack ) } ) # standard floating numbers representation. ex: std
add( 'fix', proc { |stack| Rpn::Core.__todo( stack ) } ) # fixed point representation. ex: 6 fix
add( 'sci', proc { |stack| Rpn::Core.__todo( stack ) } ) # scientific floating point representation. ex: 20 sci
add( 'prec', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float precision in bits. ex: 256 prec
add( 'prec', proc { |stack| Rpn::Core::Mode.prec( stack ) } )
add( 'round', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float rounding mode. ex: ["nearest", "toward zero", "toward +inf", "toward -inf", "away from zero"] round
add( 'default', proc { |stack| Rpn::Core.__todo( stack ) } ) # set float representation and precision to default
add( 'type', proc { |stack| Rpn::Core.__todo( stack ) } ) # show type of stack first entry
add( 'default', proc { |stack| Rpn::Core::Mode.default( stack ) } )
add( 'type', proc { |stack| Rpn::Core::Mode.type( stack ) } )
# TEST
add( '>', proc { |stack| Rpn::Core.__todo( stack ) } ) # binary operator >
@ -165,9 +165,9 @@ module Rpn
add( 'atanh', proc { |stack| Rpn::Core.__todo( stack ) } ) # inverse hyperbolic tangent
# TIME AND DATE
add( 'time', proc { |stack| Rpn::Core.__todo( stack ) } ) # time in local format
add( 'date', proc { |stack| Rpn::Core.__todo( stack ) } ) # date in local format
add( 'ticks', proc { |stack| Rpn::Core.__todo( stack ) } ) # system tick in µs
add( 'time', proc { |stack| Rpn::Core::TimeDate.time( stack ) } )
add( 'date', proc { |stack| Rpn::Core::TimeDate.date( stack ) } )
add( 'ticks', proc { |stack| Rpn::Core::TimeDate.ticks( stack ) } )
end
def add( name, implementation )

33
lib/language/mode.rb Normal file
View file

@ -0,0 +1,33 @@
module Rpn
module Core
module Mode
module_function
# set float precision in bits. ex: 256 prec
def prec( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
Rpn::Core.precision = args[0][:value]
stack
end
# set float representation and precision to default
def default( stack )
Rpn::Core.precision = 12
stack
end
# show type of stack first entry
def type( stack )
stack, args = Rpn::Core.stack_extract( stack, [:any] )
stack << args[0]
stack << { type: :string,
value: args[0][:type].to_s }
stack
end
end
end
end

View file

@ -88,6 +88,14 @@ module Rpn
stack << { type: :numeric,
value: args[0][:value]**args[1][:value] }
end
# rpn_square root
def sqrt( stack )
stack, args = Rpn::Core.stack_extract( stack, [%i[numeric]] )
stack << { type: :numeric,
value: BigMath.sqrt( BigDecimal( args[0][:value] ), Rpn::Core.precision ) }
end
end
end
end

29
lib/language/time-date.rb Normal file
View file

@ -0,0 +1,29 @@
require 'date'
module Rpn
module Core
module TimeDate
module_function
# time in local format
def time( stack )
stack << { type: :string,
value: Time.now.to_s }
end
# date in local format
def date( stack )
stack << { type: :string,
value: Date.today.to_s }
end
# system tick in µs
def ticks( stack )
ticks_since_epoch = Time.utc( 1, 1, 1 ).to_i * 10_000_000
now = Time.now
stack << { type: :numeric,
value: now.to_i * 10_000_000 + now.nsec / 100 - ticks_since_epoch }
end
end
end
end

View file

@ -15,6 +15,8 @@ module Rpn
@dictionary = Dictionary.new
@parser = Parser.new
@runner = Runner.new
Rpn::Core.init
end
def run

View file

@ -0,0 +1,32 @@
# coding: utf-8
# frozen_string_literal: true
require 'test/unit'
require_relative '../lib/core'
class TestParser < Test::Unit::TestCase
def test_time
now = Time.now.to_s
stack = Rpn::Core::TimeDate.time( [] )
assert_equal [{ value: now, type: :string }],
stack
end
def test_date
now = Date.today.to_s
stack = Rpn::Core::TimeDate.date( [] )
assert_equal [{ value: now, type: :string }],
stack
end
def test_ticks
stack = Rpn::Core::TimeDate.ticks( [] )
# TODO: better test, but how?
assert_equal :numeric,
stack[0][:type]
end
end