-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved the icu lib to icu folder, created initial decimal plugin in de…
…cimal folder
- Loading branch information
1 parent
d05ce17
commit dcd100b
Showing
46 changed files
with
20,776 additions
and
20,451 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
Oops, something went wrong.