Skip to content

Commit

Permalink
Moved the icu lib to icu folder, created initial decimal plugin in de…
Browse files Browse the repository at this point in the history
…cimal folder
  • Loading branch information
adesutherland committed Sep 16, 2024
1 parent d05ce17 commit dcd100b
Show file tree
Hide file tree
Showing 46 changed files with 20,776 additions and 20,451 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@ endif ()
include(CTest)
add_subdirectory(re2c)
add_subdirectory(lemon)
add_subdirectory(decimal)
add_subdirectory(platform)
add_subdirectory(avl_tree)
add_subdirectory(cpacker)
add_subdirectory(compiler)
add_subdirectory(machine)
add_subdirectory(assembler)
add_subdirectory(disassembler)
add_subdirectory(debugger)
add_subdirectory(decimal)
add_subdirectory(icu)

Check failure on line 27 in CMakeLists.txt

View workflow job for this annotation

GitHub Actions / Build for Ubuntu

The source directory
add_subdirectory(interpreter)
add_subdirectory(rxpa)
add_subdirectory(lib)
add_subdirectory(debugger)
add_subdirectory(tests)
add_subdirectory(bin)

Expand Down
38 changes: 35 additions & 3 deletions decimal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
cmake_minimum_required(VERSION 3.10)

project(Decimal C)
project(DecimalPlugins C)

set(CMAKE_C_STANDARD 90)

add_library(decimal decNumber.h decNumber.c decContext.h decContext.c)
target_include_directories(decimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
add_library(icudecimal icudecimal.c decplugin.h)
target_include_directories(icudecimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(icudecimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../icu)
target_include_directories(icudecimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../interpreter)
target_link_libraries(icudecimal icu)
add_dependencies(icudecimal icu)

# Add the test1 executable
add_executable(icudecimal_test icudecimal_test.c)
target_include_directories(icudecimal_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../interpreter)
target_link_libraries(icudecimal_test icudecimal)

# Enable Testing
enable_testing()
# Add the first test - 32 digits, with arguments 1, 2 and check that the output are:
# ADD 3
# SUB 1
# MUL 2
# DIV 0.5
add_test(icudecimal_test1 icudecimal_test 32 1 2)
set_tests_properties(icudecimal_test1 PROPERTIES PASS_REGULAR_EXPRESSION "ADD 3")
set_tests_properties(icudecimal_test1 PROPERTIES PASS_REGULAR_EXPRESSION "SUB 1")
set_tests_properties(icudecimal_test1 PROPERTIES PASS_REGULAR_EXPRESSION "MUL 2")
set_tests_properties(icudecimal_test1 PROPERTIES PASS_REGULAR_EXPRESSION "DIV 0.5")

# Add the second test - 32 digits, with 32 digit arguments and check output
# ADD 30000000000000000000000000000000
# SUB -10000000000000000000000000000000
# MUL 2.0000000000000000000000000000000E+62
# DIV 0.5
add_test(icudecimal_test2 icudecimal_test 32 10000000000000000000000000000000 20000000000000000000000000000000)
set_tests_properties(icudecimal_test2 PROPERTIES PASS_REGULAR_EXPRESSION "ADD 30000000000000000000000000000000")
set_tests_properties(icudecimal_test2 PROPERTIES PASS_REGULAR_EXPRESSION "SUB -10000000000000000000000000000000")
set_tests_properties(icudecimal_test2 PROPERTIES PASS_REGULAR_EXPRESSION "MUL 2.0000000000000000000000000000000E+62")
set_tests_properties(icudecimal_test2 PROPERTIES PASS_REGULAR_EXPRESSION "DIV 0.5")
35 changes: 35 additions & 0 deletions decimal/decplugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Created by Adrian Sutherland on 15/09/2024.
//

#ifndef CREXX_DECPLUGIN_H
#define CREXX_DECPLUGIN_H

#include "rxvalue.h" /* For value */

/* Structure for the decimal plugin with all the function pointers for decimal
* maths operatoins and a private pointer for the decimal context to be used by
* the different implementations of the decimal plugin */
typedef struct decpugin decplugin;
struct decpugin {
void *private_context;
size_t (*getDigits)(decplugin *plugin);
void (*setDigits)(decplugin *plugin, size_t digits);
size_t (*getRequiredStringSize)(decplugin *plugin);
void (*decFloatFromString)(decplugin *plugin, value *result, const char *string);
void (*decFloatToString)(decplugin *plugin, const value *number, char *string);

void (*decFloatAdd)(decplugin *plugin, value *result, const value *op1, const value *op2);
void (*decFloatSub)(decplugin *plugin, value *result, const value *op1, const value *op2);
void (*decFloatMul)(decplugin *plugin, value *result, const value *op1, const value *op2);
void (*decFloatDiv)(decplugin *plugin, value *result, const value *op1, const value *op2);
};

/* Function to create a new decimal plugin */
decplugin *new_decplugin();

/* Function to destroy a decimal plugin */
void destroy_decplugin(decplugin *plugin);


#endif //CREXX_DECPLUGIN_H
148 changes: 148 additions & 0 deletions decimal/icudecimal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Description: This file contains the implementation of the decimal plugin using the ICU
* decNumnerlibrary.
*
* Created by Adrian Sutherland on 15/09/2024.
*
* -------------------------------------------------------------------------------
* The following parameters have been tuned in icu decNumber for CREXX:
* DECDPUN = 8 # For 64-bit (Overriding 3)
* DECNUMDIGITS = 64 # Default (Overriding 100)
* DECBUFFER = 64 # Internal Buffer size avoiding malloc (Overriding 36)
* DECUSE64 = 1 # 64-bit (Default)
* DECEXTFLAG = 1 # Extended set of flags (Default)
* DECSUBSET = 0 # No subset - possibly higher performance (Default)
* -------------------------------------------------------------------------------
*/
#include "decplugin.h"
#include "decNumber.h"
#include "decNumberLocal.h"

/* Ensure that the decNumber is big enough to hold the number */
static void EnsureCapacity(value *number, size_t digits) {
/* Calculate the size of the decNumber */

/* How many units are necessary, this is the ceil(digits/DECDPUN) */
size_t units = (digits + DECDPUN - 1) / DECDPUN;
size_t size;

/* DECNUMUNITS is the default (minimum) number of units needed - do we need more? */
if (units > DECNUMUNITS) {
size = sizeof(decNumber) + ((units - DECNUMUNITS) * sizeof(decNumberUnit));
}
else {
size = sizeof(decNumber);
}

/* If the value has a decimal buffer already */
if (number->decimal_value) {

/* If the size is bigger than the current size, reallocate the memory */
if (size > number->decimal_value_length) {
/* Allocate the new memory */
decNumber *new_value = realloc(number->decimal_value, size);

/* If the reallocation was unsuccessful, panic as per crexx standard behavior */
if (new_value == NULL) {
fprintf(stderr, "PANIC: Unable to reallocate memory for decNumber\n");
exit(1);
}
number->decimal_value = new_value;
number->decimal_value_length = size;
}
}
else {
/* Allocate the memory for the decNumber */
number->decimal_value = malloc(size);
number->decimal_value_length = size;
}
}

/* Definitions of each of the decimal functions */

/* Get the number of digits in the decimal context */
size_t getDigits(decplugin *plugin) {
return ((decContext*)(plugin->private_context))->digits;
}

/* Set the number of digits in the decimal context */
void setDigits(decplugin *plugin, size_t digits) {
((decContext*)(plugin->private_context))->digits = (int32_t)digits;
}

/* Get the required string size for the decimal context */
size_t getRequiredStringSize(decplugin *plugin) {
return ((decContext*)(plugin->private_context))->digits + 14;
}

/* Convert a string to a decimal number */
void decFloatFromString(decplugin *plugin, value *result, const char *string) {
decContext *context = (decContext*)(plugin->private_context);
EnsureCapacity(result, context->digits);
decNumberFromString(result->decimal_value, string, context);
}

/* Convert a decimal number to a string */
/* The sttring must be allocated by the caller and should be at least
* getRequiredStringSize() bytes */
void decFloatToString(decplugin *plugin, const value *number, char *string) {
decContext *context = (decContext*)(plugin->private_context);
decNumberReduce(number->decimal_value, number->decimal_value, context);
decNumberToString(number->decimal_value, string);
}

/* Add two decimal numbers */
void decFloatAdd(decplugin *plugin, value *result, const value *op1, const value *op2) {
EnsureCapacity(result, ((decContext*)(plugin->private_context))->digits);
decNumberAdd(result->decimal_value, op1->decimal_value, op2->decimal_value, (decContext*)(plugin->private_context));
}

/* Subtract two decimal numbers */
void decFloatSub(decplugin *plugin, value *result, const value *op1, const value *op2) {
EnsureCapacity(result, ((decContext*)(plugin->private_context))->digits);
decNumberSubtract(result->decimal_value, op1->decimal_value, op2->decimal_value, (decContext*)(plugin->private_context));
}

/* Multiply two decimal numbers */
void decFloatMul(decplugin *plugin, value *result, const value *op1, const value *op2) {
EnsureCapacity(result, ((decContext*)(plugin->private_context))->digits);
decNumberMultiply(result->decimal_value, op1->decimal_value, op2->decimal_value, (decContext*)(plugin->private_context));
}

/* Divide two decimal numbers */
void decFloatDiv(decplugin *plugin, value *result, const value *op1, const value *op2) {
EnsureCapacity(result, ((decContext*)(plugin->private_context))->digits);
decNumberDivide(result->decimal_value, op1->decimal_value, op2->decimal_value, (decContext*)(plugin->private_context));
}

/* Function to create a new decimal plugin */
decplugin *new_decplugin() {
/* Allocate memory for the context */
decContext* context = malloc(sizeof(decContext));
decContextDefault(context, DEC_INIT_BASE); // initialize
context->traps = 0; // no traps
context->digits = DECNUMDIGITS; // set precision

/* Allocate memory for the plugin */
decplugin *plugin = malloc(sizeof(decplugin));
plugin->private_context = context;
plugin->getDigits = getDigits;
plugin->setDigits = setDigits;
plugin->getRequiredStringSize = getRequiredStringSize;
plugin->decFloatFromString = decFloatFromString;
plugin->decFloatToString = decFloatToString;
plugin->decFloatAdd = decFloatAdd;
plugin->decFloatSub = decFloatSub;
plugin->decFloatMul = decFloatMul;
plugin->decFloatDiv = decFloatDiv;


return plugin;
}

/* Function to destroy a decimal plugin */
void destroy_decplugin(decplugin *plugin) {
free(plugin->private_context);
free(plugin);
}

70 changes: 70 additions & 0 deletions decimal/icudecimal_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//
// Created by Adrian Sutherland on 16/09/2024.
//
// ICU Decimal Test 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "decplugin.h"

int main(int argc, char *argv[]) {
decplugin *plugin = new_decplugin();
value a, b, result;


if (argc < 4) {
printf("Please supply the number of digits, and two numbers to add.\n");
return 1;
}

// Set the number of digits in the decimal context
plugin->setDigits(plugin, atoi(argv[1]));

/* Make a string buffer to hold the result */
char* string = malloc(plugin->getRequiredStringSize(plugin));

a.decimal_value = NULL;
b.decimal_value = NULL;
result.decimal_value = NULL;

// Convert the arguments to decimal numbers
plugin->decFloatFromString(plugin, &a, argv[2]);
plugin->decFloatFromString(plugin, &b, argv[3]);

// Add the numbers and print the result
plugin->decFloatAdd(plugin, &result, &a, &b);
plugin->decFloatToString(plugin, &result, string);
printf("ADD %s\n", string);

// Subtract the numbers and print the result
plugin->decFloatSub(plugin, &result, &a, &b);
plugin->decFloatToString(plugin, &result, string);
printf("SUB %s\n", string);

// Multiply the numbers and print the result
plugin->decFloatMul(plugin, &result, &a, &b);
plugin->decFloatToString(plugin, &result, string);
printf("MUL %s\n", string);

// Divide the numbers and print the result
plugin->decFloatDiv(plugin, &result, &a, &b);
plugin->decFloatToString(plugin, &result, string);
printf("DIV %s\n", string);

// Free the memory
if (a.decimal_value) {
free(a.decimal_value);
}
if (b.decimal_value) {
free(b.decimal_value);
}
if (result.decimal_value) {
free(result.decimal_value);
}
free(string);

destroy_decplugin(plugin);
return 0;
} // main

Loading

0 comments on commit dcd100b

Please sign in to comment.